3

I have a wxPython gui and I want to programmatically generate an event.

I've tried a syntax like this:

e = wx.Event.__init__(grid, eventType=wx.EVT_LEFT_DOWN)

which results in:

TypeError: unbound method __init__() must be called with Event instance as first argument (got Grid instance instead)

or:

 e = wx.CommandEvent(commandType=wx.EVT_BUTTON)

TypeError: in method 'new_CommandEvent', expected argument 1 of type 'wxEventType'

So question is simply, what is the exact, literal syntax that I need to use to create an event object? Or, can someone point me to a good resource for making sense of events? I don't know if I'm just missing something simple in my understanding. I haven't been able to find a direct answer to this question yet online. I checked out this question: Generate a custom CommandEvent in wxPython , but I don't want to make a custom event.

Thanks in advance!

0

4 Answers 4

4

You would want to use wx.PostEvent

To programatically generate an event:

wx.PostEvent(self.GetEventHandler(), wx.PyCommandEvent(wx.EVT_BUTTON.typeId, self.GetId()))

if you want to post a wx.EVT_BUTTON event. Making it a PyCommandEvent means it will propagate upwards; other event types don't propagate by default.

The general form of wx.PostEvent(): http://www.wxpython.org/docs/api/wx-module.html#PostEvent

Here's a small example code:

import wx

class MyFrame ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Test", pos = wx.DefaultPosition, size = wx.Size( 200,200 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        sizer_inside = wx.BoxSizer( wx.VERTICAL )

        # Adding a button and a textCtrl widget
        self.button = wx.Button( self, wx.ID_ANY, u"Click Me", wx.DefaultPosition, wx.DefaultSize, 0 )
        sizer_inside.Add( self.button, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
        self.textCtrl = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_NO_VSCROLL )
        sizer_inside.Add( self.textCtrl, 0, wx.ALIGN_CENTER|wx.ALL, 5 )

        self.SetSizer( sizer_inside )
        self.Layout()
        self.Centre( wx.BOTH )
        self.Show()

        self.counter = 0

        # Binding Events
        self.Bind( wx.EVT_BUTTON, self.on_click )
        self.Bind( wx.EVT_CHOICE, self.test_dummy)

    #Event handlers
    def on_click( self, event ):
        self.counter += 1
        wx.PostEvent(self.GetEventHandler(), wx.PyCommandEvent(wx.EVT_CHOICE.typeId, self.GetId()))

    def test_dummy(self, event):
        self.counter += 1
        self.textCtrl.SetValue(str(self.counter))

if __name__ == "__main__":
    app = wx.App(False)
    MyFrame(None)
    app.MainLoop()

If you run this, notice that the textCtrl will display 2 after clicking the button. The first event handler manually fires the second event which is handled by test_dummy.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks.. the key information that I didn't understand was that wx.PyCommandEvent takes an integer. Also, thanks to the other answerers for pointing out the wx.wxEVT_* syntax.
1

I think you'd better using win32gui.PostMessage().

This would help you.

http://markmail.org/message/epiclzlaph44f3kk

2 Comments

You should add the relevant code to your answer, in case that link ever goes dead. Also, we don't know for sure that the OP is using Windows, or that a Windows-only solution is acceptable for him/her.
thanks, this saved me. I was trying to call the Next button on WxPython under Windows. If I understand correctly, since this is a Windows class (and not a pythonic class) I could not use a pythonic event. I therefore had to call the windows event. When I did try to use a pythonic event my wizard would just end without going through the pages as if I pressed the "Finish" button even though it was not visible on the page. Perhaps a different strategy would have been to switch from a windows Wizard class to a pythonic wizard class but I didn't try it.
1

Use wx.PostEvent... like so:

class launcherWindow(wx.Frame):
    def __init__(self):
    wx.Frame.__init__(self, parent=None, title='New Window')
    #now add the main body, start with a panel
    panel = wx.Panel(self)
    #instantiate a new dropdown
    self.productDropDown = wx.ComboBox(panel, size=wx.DefaultSize, style = wx.CB_READONLY)

    #get the products and product subtypes
    self.productDict = self.getProductsAndSubtypes()

    #setup subtypes first, just in case, since onProductSelection will reference this
    self.productSubtypeDropDown = wx.ComboBox(panel, size=wx.DefaultSize, style = wx.CB_READONLY)

    #add products
    for product in self.productDict.keys():
        self.productDropDown.Append(product)

    #bind selection event
    self.productDropDown.Bind(wx.EVT_COMBOBOX, self.onProductSelection)

    #set default selection
    self.productDropDown.SetSelection(0)

    #pretend that we clicked the product selection, so it's event gets called
    wx.PostEvent(self.productDropDown, wx.CommandEvent(wx.wxEVT_COMMAND_COMBOBOX_SELECTED))

    #now add the dropdown to a sizer, set the sizer for the panel, fit the panel, etc...

def onProductSelection(self, event):
    productSelected = self.productDropDown.GetStringSelection()
    productSubtypes = self.productDict[productSelected]

    #clear any existing product subtypes, since each product may have different ones
    self.productSubtypeDropDown.Clear()

    for productSubtype in productSubtypes:
        self.productSubtypeDropDown.Append(productSubtype)

    #select the first item by default
    self.productSubtypeDropDown.SetSelection(0)

Comments

0

thanks. @i5on9i comment saved me.

I was trying to call the Next button on WxPython under Windows.

When I did try to use a pythonic event my wizard would just end without going through the pages as if I pressed the "Finish" button even though it was not visible on the page.

If I understand correctly, since this is a Windows class (and not a pythonic class) I could not use a pythonic event. I therefore had to call the windows event.

Perhaps a different strategy would have been to switch from a windows Wizard class to a pythonic wizard class but I didn't try it.

BTW the message I ended up sending was:

win32gui.PostMessage(wizard.GetHandle(),0x0111,wx.ID_FORWARD,self.wizard.FindWindowById(wx.ID_FORWARD).GetHandle())

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.