pythonwxpythonwxwidgets

How to pass custom data in event wxWidgets


Situation

I am currently writing an app with wxPython (wxWidgets for Python).

In this app is displayed a list of conversations, with an "Open conversation" button at the end of each row. Let's call this window "All conversations".

Clicking any one of the buttons calls the function "open_conversation(self, event)", which displays the full conversation.

What I want to do is, at the generation of the window "All conversations", pass some custom data in each "Bind" event or in each "wxButton" object, such as a string (the name of the contact for instance) ; afterwards, when a button is clicked, it will pass said data in the "event" argument, becoming accessible in the function with something like contact = event.CustomData["recipient"].

Issue

Referring to the documentation, I found the "userData" keyword for the "Bind" method, but it looks like it doesn't work in Python.

self.openConversation_button.Bind(wx.EVT_BUTTON, self.open_conversation, userData="test")
TypeError: _EvtHandler_Bind() got an unexpected keyword argument 'userData'

Update

I've marked the solution of Rolf of Saxony as correct because it fits my need best, however I'd advise in general to use the custom event system as suggested by VZ.


Solution

  • An easy way to pass custom data into a callback event is to use a lambda function.
    e.g.

    import wx
    
    class ButtonFrame(wx.Frame):
        def __init__(self, value):
            wx.Frame.__init__(self,None)
            self.btn1 = wx.Button(self, -1, ("a"))
            self.btn2 = wx.Button(self, -1, ("b"))
            self.btn3 = wx.Button(self, -1, ("No flag"))
            self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)
            self.btnSizer.Add(self.btn1 , 0, wx.RIGHT, 10)
            self.btnSizer.Add(self.btn2 , 0, wx.RIGHT, 10)
            self.btnSizer.Add(self.btn3 , 0, wx.RIGHT, 10)
            self.btn1.Bind(wx.EVT_BUTTON,  lambda event: self.OnButton(event, flag="A"))
            self.btn2.Bind(wx.EVT_BUTTON,  lambda event: self.OnButton(event, flag="B"))
            self.btn3.Bind(wx.EVT_BUTTON,  self.OnButton)
            self.SetSizer(self.btnSizer)
            self.Show()
    
        def OnButton(self,event, flag=None):
            if flag:
                print ("Button pressed was "+flag)
            else:
                print ("A button got pressed")
    
    if __name__ == "__main__":
        app = wx.App()
        ButtonFrame(None)
        app.MainLoop()