Page 1 of 1

How to handle Events in another Python Script using PyCEGUI

Posted: Wed Apr 13, 2011 15:28
by pizzazhang
Hi, everybody:
I'm new to python but I try to do something using PyOgre and PyCEGUI. My problem is: I want to put the window events handler in another python script file, just like using lua script when I use C++ CEGUI. Here is what I do to implement :
in my demo.py:

Code: Select all

    def _createScene(self):
        mygui = MYGUI.getSingleton()
        execfile('gui_logic.py')

the first line in this function I just setup CEGUI and set resource location etc.
then I execute a python file using execfile

in my events handler file -- gui_logic.py:

Code: Select all

class GuiLogic:
    def btn_clicked(self, args):
        button = MYGUI.getSingleton().getWindow("Root/BgImg/QuitBtn")
        button.setText("HAHA")
        return True

    def subscribe(self):
        MYGUI.getSingleton().loadWindow("Root")
        button = MYGUI.getSingleton().getWindow("Root/BgImg/QuitBtn")
        button.subscribeEvent(CEGUI.PushButton.EventClicked,
                              self,
                              "btn_clicked")


if __name__=='__main__':
    GuiLogic().subscribe()


I don't want to be implement these in a class but the subscribeEvent function takes
three arguments so... anyway when I launch the demo, it successfully load the layoutfile

Code: Select all

13/04/2011 23:07:37 (Std)    ---- Successfully completed loading of GUI layout from 'Root.layout' ----
which I checked in log file.
Here is my problem: when I clicked the button, the program crashed! I don't know why because the log files and Eclipse(I use Eclipse and PyDev) give me no error track information!
So I really want to know how to handler CEGUI window events in another python script file just like lua does! I can easily use tolua++ handle a big part of my Class function in a lua script but now in Python I really don't know how to do.

Any advice will be appreciated!

Re: How to handler Events in another Python Script using PyC

Posted: Wed Apr 13, 2011 15:39
by Kulik
It's because you aren't referencing GuiLogic class in python at any place, it gets garbage collected and boom! This is one of the dangers of C++ and Python interactions. I think I may be able to somehow solve this my increasing refcount of given instance when subscribing but it would probably slow things down a bit, I will consider it though.

Always make sure that what you pass to CEGUI is referenced in your python code somewhere (it's refcount doesn't drop to 0)

Re: How to handler Events in another Python Script using PyC

Posted: Thu Apr 14, 2011 04:45
by pizzazhang
Kulik wrote:It's because you aren't referencing GuiLogic class in python at any place, it gets garbage collected and boom! This is one of the dangers of C++ and Python interactions. I think I may be able to somehow solve this my increasing refcount of given instance when subscribing but it would probably slow things down a bit, I will consider it though.

Always make sure that what you pass to CEGUI is referenced in your python code somewhere (it's refcount doesn't drop to 0)


Thank you first for your reply. Now I changed my code in this way :

Code: Select all

class GuiLogic:
    def btn_clicked(self, args):
        button = CEGUI.WindowManager.getSingleton().getWindow("Root/BgImg/QuitBtn")
        button.setText("HAHA")
        return True

    def subscribe(self):
        sheet = CEGUI.WindowManager.getSingleton().loadWindowLayout("Root.layout")
        CEGUI.System.getSingleton().setGUISheet(sheet)
        button = CEGUI.WindowManager.getSingleton().getWindow("Root/BgImg/QuitBtn")
        button.subscribeEvent(CEGUI.PushButton.EventClicked,
                              self,
                              "btn_clicked")

I removed MyGUISystem(I put CEGUI handlers in this class but I think my problems comes here) in gui_logic.py.
Also I didn't put main in gui_logic.py but I call GuiLogic's function subscribe in createScene in demo.py:

Code: Select all

    def _createScene(self):
        MYGUI.getSingleton()
        GuiLogic().subscribe()

everything seems working but when I clicked the button, I got

Code: Select all

AttributeError: 'tuple' object has no attribute 'btn_clicked'

I think the error comes in subscribeEvent(param1, param2, param3)
if I put this function in demo.py it just works perfect but in another class...I got confused.
I looked into the cegui demos that py-ogre has and I didn't find any samples that putting gui logic in another python file. So if someone gives such a sample I will really really appreciate his/her work!

Re: How to handle Events in another Python Script using PyCE

Posted: Thu Apr 14, 2011 14:04
by pizzazhang
Finally I solved it. I'm new to Python so I know little about Python's garbage collection as Kulik mentioned.
In C++ we used to clean the resource by ourselves but in Python it is automatic. I read Kulik's advice again and
search some python knowledge, finally just a little change and my program works right:
in demo.py:

Code: Select all

        self.logic = gui_logic.GuiLogic()
        self.logic.subscribe()

use self.logic to store the ref to GuiLogic instance so that Python won't immediately clean up the reference.

But it's still not convenient for me because in C++ I just execute a lua script file in my code and not instance a class(handle all events in lua, and function subscibe() in lua only takes a Event name and a function name as arguments), but in Python now I must instance a class in code and write event handlers in a class because function subscribe() must take a Class ref argument in the second place.
I know not everything is perfect so I shouldn't blame too much on Python. Also I shouldn't compare between Python and lua since they apply in a different area. I like Python so I should get used to the Python Way which is very different to C++ :D

Re: How to handle Events in another Python Script using PyCE

Posted: Thu Apr 14, 2011 15:19
by Kulik
You can subscribe to free functions but I have no idea how python deals with them, if the same pitfalls apply.

subscribeEvent("EventName", someFreeFunction) should work too

Re: How to handle Events in another Python Script using PyCE

Posted: Thu Apr 14, 2011 16:57
by pizzazhang

Code: Select all

import ogre.gui.CEGUI as CEGUI

       
def btn_clicked(args):
    button = CEGUI.WindowManager.getSingleton().getWindow("Root/BgImg/QuitBtn")
    button.setText("HAHA")
    return True

def subscribe():
    sheet = CEGUI.WindowManager.getSingleton().loadWindowLayout("Root.layout")
    CEGUI.System.getSingleton().setGUISheet(sheet)
    button = CEGUI.WindowManager.getSingleton().getWindow("Root/BgImg/QuitBtn")
    button.subscribeEvent("Clicked",
                          btn_clicked)

if __name__ == '__main__':
    subscribe()

I got this:

Code: Select all

  File "gui_logic.py", line 23, in <module>
    subscribe()
  File "gui_logic.py", line 20, in subscribe
    btn_clicked)
NameError: global name 'btn_clicked' is not defined


If I change btn_clicked to string like in lua, I got this:

Code: Select all

  File "gui_logic.py", line 20, in subscribe
    "btn_clicked")
Boost.Python.ArgumentError: Python argument types in
    EventSet.subscribeEvent(PushButton, str, str)
did not match C++ signature:
    subscribeEvent(class CEGUI::Tree *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::EventSet *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::System *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::MouseCursor *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Window *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::MultiColumnList *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::DragContainer *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::RadioButton *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Spinner *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Slider *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Thumb *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Editbox *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::FrameWindow *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::GUISheet *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Scrollbar *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Checkbox *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Combobox *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Listbox *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::Titlebar *, class CEGUI::String, struct _object *, class CEGUI::String)
    subscribeEvent(class CEGUI::PushButton *, class CEGUI::String, struct _object *, class CEGUI::String)

it seems in Python I only can use function subscribeEvent() with 3 arguments, but in C++, yes, what you mentioned works well.

Re: How to handle Events in another Python Script using PyCE

Posted: Fri Apr 15, 2011 07:23
by dermont
pizzazhang wrote:it seems in Python I only can use function subscribeEvent() with 3 arguments, but in C++, yes, what you mentioned works well.


For python-ogre the SubscribeEvent format is explained here:
http://www.ogre3d.org/addonforums/viewt ... ent#p15968

Code: Select all

    .subscribeEvent(CEGUI.PushButton.EventClicked, self, "handleQuit")
    .subscribeEvent(CEGUI.PushButton.EventClicked, freefunction, "")


For example from Demo_CEGUI_Gui_2.py:

Code: Select all

eb.subscribeEvent(CEGUI.Window.EventTextChanged, textChangedHandler,"")


pizzazhang wrote:I looked into the cegui demos that py-ogre has and I didn't find any samples that putting gui logic in another python file. So if someone gives such a sample I will really really appreciate his/her work!


Try the following link I think that is what you are looking for:
http://groups.google.com/group/python-o ... t&q=cegui#

Re: How to handle Events in another Python Script using PyCE

Posted: Fri Apr 15, 2011 10:05
by pizzazhang
For example from Demo_CEGUI_Gui_2.py:

Code: Select all

eb.subscribeEvent(CEGUI.Window.EventTextChanged, textChangedHandler,"")

'dermont':
Fixed. Tank you very very much. Yeah, I just missed such thing in cegui demos. I should check the sample code more carefully next time! Really appreciate your help!

Re: How to handle Events in another Python Script using PyCE

Posted: Fri Apr 15, 2011 13:34
by Kulik
Yeah, it would be great if someone added these to the wiki.

Re: How to handle Events in another Python Script using PyCE

Posted: Fri Apr 15, 2011 15:59
by Jamarr
It would also be great if new users stop posting their "usage" questions in the "chit-chat and off-topic" forum so I would not have to move them into the "beginners help" forum every other day. :hammer: