Search code examples
pythonwxpython

What is the difference between parent.Bind and widget.Bind in wxPython


import wx

class MyPanel(wx.Panel):

    def __init__(self, parent):
        super().__init__(parent)
        btn = wx.Button(self, label="Press me")
        btn.Bind(wx.EVT_BUTTON, self.on_button_press)

    def on_button_press(self, event):
        print("You pressed the button")

class MyFrame(wx.Frame):

    def __init__(self):
        super().__init__(parent=None, title="Hello wxPython")
        panel = MyPanel(self)
        self.Show()

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

In the code above we used btn.Bind for binding wx.Button to wx.EVT_BUTTON.
if instead, we use this way: self.Bind(wx.EVT_BUTTON, self.on_button_press, btn)
The result will be the same as above. Now my question is the difference between self.Bind and btn.Bind.


Solution

  • Each widget has an Id.
    Events when triggered, pass the Id of the triggering widget, in this case a button.
    Binding an event to a function can be specific or generic i.e. a specific widget or any widget that fires that event type.
    In short, in this case, the self.Bind binds any button event unless you specify a widget ID.
    See: https://docs.wxpython.org/events_overview.html
    Hopefully, the code below will help explain.
    N.B. event.Skip() says don't stop at this event, see if there are more events to process.

    import wx
    
    class MyPanel(wx.Panel):
    
        def __init__(self, parent):
            super().__init__(parent)
            btn1 = wx.Button(self, label="Press me 1", pos=(10,10))
            btn2 = wx.Button(self, label="Press me 2", pos=(10,50))
            Abtn = wx.Button(self, label="Press me", pos=(10,90))
    
        # Bind btn1 to a specific callback routine
            btn1.Bind(wx.EVT_BUTTON, self.on_button1_press)
        # Bind btn2 to a specific callback routine specifying its Id
        # Note the order of precedence in the callback routines
            self.Bind(wx.EVT_BUTTON, self.on_button2_press, btn2)
        # or identify the widget via its number
        #    self.Bind(wx.EVT_BUTTON, self.on_button2_press, id=btn2.GetId())
        # Bind any button event to a callback routine
            self.Bind(wx.EVT_BUTTON, self.on_a_button_press)
    
        # button 1 pressed
        def on_button1_press(self, event):
            print("You pressed button 1")
            event.Skip()
    
        # button  2 pressed
        def on_button2_press(self, event):
            print("You pressed button 2")
            event.Skip()
    
        # Any button pressed
        def on_a_button_press(self, event):
            print("You pressed a button")
            event.Skip()
    
    class MyFrame(wx.Frame):
    
        def __init__(self):
            super().__init__(parent=None, title="Hello wxPython")
            panel = MyPanel(self)
            self.Show()
    
    if __name__ == "__main__":
        app = wx.App(redirect=False)
        frame = MyFrame()
        app.MainLoop()