Example of OOP GUI App needed.
BlitzMax Forums/BlitzMax Beginners Area/Example of OOP GUI App needed.
| ||
I've had to start from scratch with my app and want to go about it using OOP. Can anyone post some code that shows how to create a window with a canvas but using OOP and being able to check for events? It may sound like a lot but I kind of don't know where to start. In the mean time I'll start coding. Thanks :) |
| ||
Strict Type TAmon Field window:TGadget Field canvas:TGadget Field button:TGadget Field clsR:Byte Field clsG:Byte Field clsB:Byte Method ev() If EventSource()=canvas If EventID()=EVENT_GADGETPAINT update EndIf If EventID()=EVENT_MOUSEMOVE clsR=EventX() clsG=EventY() update EndIf EndIf If EventSource()=button clsR=Rnd(255) clsG=Rnd(255) clsB=Rnd(255) update EndIf End Method Method update() SetGraphics CanvasGraphics(canvas) SetClsColor clsR,clsG,clsB Cls Flip End Method End Type ' ' a seperate create function to make it a bit more like the other blitz commands ' Function CreateAmon:TAmon(x:Int,y:Int,w:Int,h:Int) Local a:TAmon=New TAmon a.window=CreateWindow("kamikaze",x,y,w,h) a.canvas=CreateCanvas(0,0,w-80,h,a.window) a.button=CreateButton("O_o",w-80,0,70,32,a.window) SetGadgetLayout a.canvas,1,0,1,0 Return a End Function Local a:TAmon=CreateAmon(32,32,512,256) OnEnd quit Repeat WaitEvent() a.ev If EventID()=EVENT_WINDOWCLOSE End Forever Function quit() GCCollect() End End Function Note that it still has manual event-checking (a.ev), haven't 100% got yet how to do the eventhook stuff, and how to emit events. It's probably not that hard, but the manual is kinda minimalistic on that.. |
| ||
This is perfect. Thanks dude. :) |
| ||
Heres a quick demo using an eventhook... |
| ||
Fab! Finally an eventhook example that isn't written for cyborgs! Examples should be minimalistic, lotsa examples are often large pieces o' non-modular code. Papa^2 ! Now, can you add the same style o' tut to this about own events? imagine this chunk being added to your mainloop, right under Waitevent() If EventID()= <New custom ID number here> If EventSource()=<ID of source here> Notify "papa!" EndIf EndIf Now for example let a mousedown on that canvase create a new eventID. Meaning I can work with such an object *everywhere* (since EventID(), EventSource() and all the other Event-things are globals) So in short: mousedown on canvas should trigger the notify 'papa!' |
| ||
. I try to keep the main loop empty, thats what events are for ;) |
| ||
no, globally I meant, not as part of the object, it really has to emit an event. Imagine I'm making a GUI-object like a spinner orso, I simply create it like any other gadget, and anywhere in any part of the whole source, in any object, I should be able to read it out by checking the globals EventID() etc. |
| ||
Mind you the custom event could also be caught by the eventhook :) |
| ||
Nicenice! For completeness and non-globalness I'd say: Const CustomEvent = 1 (..) Field NewEvent:TEvent = New TEvent (..) and NewEvent.ID = CustomEvent in Method New() Saves globals.. the less globals the better, I always figure..! |
| ||
Ok, I think I get the hang of it, just before the emitevent in that method I put this: NewEvent.source=Self Et Voila, in my mainloop I can now check on EventSource being App ... and add this NewEvent.x=Event.x before the emitevent means I can readout EventX() in my mainloop .. Ok, eventhook rocks, Papa next time you should write the bmax manual ^_^ |
| ||
You got it CS, its easier than it seems isn't it :) |
| ||
Well things being easy depends on who teaches it. As good as the manual for B+ was, as weak is the manual for Bmax. While I can understand that BRL doesn't always have the time to polish manuals, it's still highly required. B+'s manual was really excellent for that matter.. One could ask on the forum, but a *lot* of coders either have their backgrounds in game-programming, which seems to lead to a completely different code-style (probably NOT event-based), or aren't thinking modular enough to come up with the perfect example-code. |
| ||
I made some GUI-object, need to add some free-up method: Method Free() End Method I figure I can kill the created gadgets easily with: Method Free() canvas=null button=null gccollect() End Method However, how do I get rid of the eventhook for this object? The manual is as zero'ish as it is ever: Function RemoveHook( id,func:Object( id,data:Object,context:Object ) ) I figure 'id' could be 'self' ? And what is that func stuff/how to use it? |
| ||
I've Updated the example with a Delete method, which is called automatically by BlitzMax when the object is released. (same as the new method is called when a new object is created) |
| ||
ah, nice. When/how is an object released actually? When I do: App=null ? Or only after App=null and some garbagecollecting? Or what else? :P |
| ||
I think the GC calls the Delete method just before it releases the object from memory (when there is no more references to that object). |
| ||
I just tested it, I put a notify "bla" in the Delete method, but nothing is ever notified when I 'End' or 'App=null'.. My OnEnd function also runs a GCCollect, so plenty o' opportunities to show my those notifications.. sofar: zippo~ |
| ||
Yeah I've just been doing that too :( Change Delete to Free and call app.free and it works. Is it a bug BRL? *EDIT* It works fine if you comment out the hook stuff. Seems that the GC never gets used because there is still a reference to the object... in the hook! so its not really a bug, should be mentioned in the docs tho ;) |
| ||
well, bug or not, I figured a manual free-up would work. The primary question was about that RemoveHook anyway. I figure my first-ever-hooked-gadget is kinda ready then, a multimulti-functional spinnergadget. ^_^ One of these days it'll appear in the code-archives. Sofar it works like other gadgets (except the gadget-modifying like Setgadgetshape etc. but I rarely/never use that anyway). An interesting thread this became, it by now contains a full howto for eventhooks, far better understandable than any other attempts I've seen sofar! |
| ||
papa to the rescue! Move the green windows around and observe! ._. SuperStrict Type Tbla Field canvas:TGadget Field c:Int Function eventhook:Object(id:Int,data:Object,context:Object) If Tbla(context) Tbla(context).ev TEvent(data);Return data EndFunction Method New() AddHook EmitEventHook,eventhook,Self End Method Method Free() RemoveHook EmitEventHook,eventhook GCCollect() End Method Method ev(event:TEvent) If Event.source=canvas If Event.id=EVENT_GADGETPAINT update EndIf End Method Method update() SetGraphics CanvasGraphics(canvas) SetClsColor c,255-c,c;Cls Flip End Method End Type Function CreateBla:Tbla(parent:TGadget) Local a:TBla=New TBla a.canvas=CreateCanvas(0,0,128,128,parent) a.c=Rnd(255) Return a End Function Local window:TGadget=CreateWindow("o_O",0,0,640,480) Local w1:TGadget=CreateWindow("1",50,50,128,128,window,1|WINDOW_CHILD) Local w2:TGadget=CreateWindow("2",90,90,128,128,window,1|WINDOW_CHILD) Local bla1:TBla=CreateBla(w1) Local bla2:TBla=CreateBla(w2) Repeat WaitEvent() If EventID()=EVENT_WINDOWCLOSE End Forever The WINDOW_CHILD is basically to blame here, without it there's no harm. However I want to make sure it's something I'm doing wrong/could fix, before it goes to the bug-submit orso. |
| ||
Its a known issue... http://www.blitzmax.com/Community/posts.php?topic=55777 |
| ||
hi with the following code:Strict Type TTestApp Field Window:TGadget = CreateWindow("",0,0,640,480) Field Button:TGadget = CreateButton("BUTTON",0,0,100,20,Window) Field Canvas:TGadget = CreateCanvas(0,20,ClientWidth(window),ClientHeight(window)-20,window,PANEL_BORDER) Method New() AddHook EmitEventHook,eventhook,Self Button.SetLayout(1,0,1,0) Canvas.SetLayout(1,1,1,1) EndMethod Function eventhook:Object(id,data:Object,context:Object) If TTestApp(context) Then TTestApp(context).OnEvent TEvent(data) Return data EndFunction Method OnEvent(event:TEvent) Select event.id Case EVENT_WINDOWCLOSE Select Event.Source Case window End End Select Case EVENT_GADGETACTION Select Event.Source Case Button Notify "You pressed the button" EndSelect Case EVENT_GADGETPAINT Select Event.Source Case Canvas SetGraphics(CanvasGraphics(canvas)) SetViewport(0,0,ClientWidth(canvas),ClientHeight(canvas)) Cls DrawText "TEST CANVAS",10,10 Flip 0 EndSelect EndSelect EndMethod EndType Global App:TTestApp = New TTestApp While True WaitEvent() Wend should i not be able to do Global App:TTestApp = New TTestApp Global App2:TTestApp = New TTestApp ...although if i do it throws and error with the line? |
| ||
Works for me. What error do you get? |
| ||
Global App:TTestApp = New TTestApp by itself is ok, but if i do Global App:TTestApp = New TTestApp Global App2:TestApp = New TTestApp it stops at the event.id with an error about accessing property of a null object? |
| ||
You said... global app2:TestApp = New TTestApp rather than global app2:TTestApp = New TTestApp Correcting that on Bmax 1.16 and it works as expected. |
| ||
sorry just my spelling mistake, it is TTestApp - its just my keyboard at work and the keys stick...lol will try again at home |