PyCEGUI events are now working!

Clay

18-10-2005 03:34:39

(Please note that in this post I refer to EventSet, don't forget that all Window classes also inherit from EventSet. IE everything I say below about EventSets apply to Window, PushButton, etc.)

After a lot of start and stop work I finally got CEGUI to bind events. This is how I am currently doing it:

quitButton = # create the control here

# events
def onQuit(args):
print "onQuit!"

ec = quitButton.subscribeEvent("Clicked", onQuit)


You can see this works in sandbox/testcegui.py. As you can see I have passed in "Clicked" instead of cegui.PushButton.EventClicked, but this will change shortly after I have properly wrapped the static strings for all EventSet subclasses (should be in the next revision).

The subscribeEvent currently returns an EventConnection object. This object has two methods, connected and disconnect. The connected method tells you whether the event is active and being called when events are triggered. The disconnect method removes the event from the EventSet it is registered to and frees the memory associated with the event. If you do not call EventConnection.disconnect() on every event you registered, or you do not call EventSet.removeAllEvents before you delete the EventSet you will create a memory leak.

It's rare that someone actually completely removes a GUI element from a program entirely. Usually it is simply hidden (or a different sheet is shown) until it is needed again. When the program ends, memory is cleaned up on its own and there shouldn't be anything to worry about. So to reiterate, unless you are trying to completely remove a widget from the program you do not need to worry about EventConnection disconnecting events, or calling removeAllEvents. You only need to do this if you are trying to completely delete a widget, not hide it.

You may be wondering why all of the issues with memory management. I think this is about the best I can do without reimplementing parts of CEGUI, which violates a major goal for us switching from Boost.Python to SWIG. The old Boost based pyogre did this much much worse. It passed a local variable as a reference to a class which held the reference. I'm shocked we didn't see massive crashes and access violations. I'm tempted to build a copy of the old pyogre just to see how this worked.

Anyway, it's not 100% finnished. There's still some cleanup to do, but I'm working on it. There may be a segfault or two if you really really push it with this, but I promise it'll be cleaned up in a day or two.

dermont

19-10-2005 07:52:47

Clay very nice work indeed, as usual with a great summary above. I've only briefly played about with the events so just a quick question. Are the correct event arguments currently being raised e.g.

- onDragDropItemLeaves(DragDropEventArgs& e)
- onEnabled(WindowEventArgs& e)

Clay

19-10-2005 08:29:30

Doh, I didn't notice that. I'll have to figure out the proper type of the EventArgs and cast it in the functor, which can be expensive if it's done every time the event is called. I wonder if I can assume a single registered event will always callback the same EventArgs type. If so I can speed it up a bit.

Sorry, I'm rambling. You can tell the quality of my posts seem to go down the later at night it gets here.

I won't be able to get around to this until thursday at the earliest.

Clay

21-10-2005 22:29:43

I finally figured out what the old Boost.Python pyogre was doing (let this be a lesson to everyone who writes "magic" that handles everything for you...it's great until you have to know how it's done). As a result, I have cleaned up the Event code so there's no chance of memory leaks now, no matter what you do with the returned value from subscribeEvent.

The correct EventArg type is next on my list.

Clay

21-10-2005 22:52:38

Ok, now event args are in:

def onQuit(args):
print `args`


Now gives:
<pyogre.cegui.WindowEventArgs; proxy of C++ CEGUI::WindowEventArgs instance at _3cf52100_p_CEGUI__WindowEventArgs>

dermont

22-10-2005 17:23:59

Do you have an example of retrieving the attributes associated, namely the window, with an WindowEventArg. What am I doing wrong?


# Window Event
def OnObjectSelection(args):
print 1
print `args`
print dir(args)
window = args.window
print type(window)
print dir(window)
print 2

red = cegui.colour(1.0, 0.0, 0.0, 0.5)
combobox=CreateControl("TaharezLook/Combobox" , "A Combo Box" ,sheet ,[0.05,0.15],[0.8,0.5],[0.01,0.01],[1.0,1.0],"a Combo Box")

# Add items to the combobox
item3 = cegui.ListboxTextItem("Combo Test1",1)
item3.setSelectionColours(red)
item3.setSelectionBrushImage("TaharezLook", "ListboxSelectionBrush")
combobox.addItem(item3)
item3.thisown = 0
e=combobox.subscribeEvent("ListSelectionAccepted", OnObjectSelection)




1
<pyogre.cegui.WindowEventArgs; proxy of C++ CEGUI::WindowEventArgs instance at _98ef6200_p_CEGUI__WindowEventArgs>
['__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'handled', 'this', 'thisown', 'window']
<type 'PySwigObject'>
[]
2

Clay

22-10-2005 21:03:30

This worked with the onExit button when I tried it (print `arg`). I might have missed an event or two. I'll have to take a look at it when I get home.