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 |