Best way to get the name of a button that called an event?
Solution 1
You could give the button a name, and then look at the name in the event handler.
When you make the button
b = wx.Button(self, 10, "Default Button", (20, 20))
b.myname = "default button"
self.Bind(wx.EVT_BUTTON, self.OnClick, b)
When the button is clicked:
def OnClick(self, event):
name = event.GetEventObject().myname
Solution 2
Take advantage of what you can do in a language like Python. You can pass extra arguments to your event callback function, like so.
import functools
def __init__(self):
# ...
for i in range(10):
name = 'Button %d' % i
button = wx.Button(parent, -1, name)
func = functools.partial(self.on_button, name=name)
button.Bind(wx.EVT_BUTTON, func)
# ...
def on_button(self, event, name):
print '%s clicked' % name
Of course, the arguments can be anything you want.
Solution 3
I recommend that you use different event handlers to handle events from each button. If there is a lot of commonality, you can combine that into a function which returns a function with the specific behavior you want, for instance:
def goingTo(self, where):
def goingToHandler(event):
self.SetTitle("I'm going to " + where)
return goingToHandler
def __init__(self):
buttonA.Bind(wx.EVT_BUTTON, self.goingTo("work"))
# clicking will say "I'm going to work"
buttonB.Bind(wx.EVT_BUTTON, self.goingTo("home"))
# clicking will say "I'm going to home"
Solution 4
Keep a dict
with keys that are the .Id
of the buttons and values that are the button names or whatever, so instead of a long if/elif
chain you do a single dict
lookup in buttonClick
.
Code snippets: in __init__
, add creation and update of the dict
:
self.panel1 = wx.Panel(self, -1)
self.thebuttons = dict()
self.button1 = wx.Button(self.panel1, id=-1,
pos=(10, 20), size = (20,20))
self.thebuttons[self.button1.Id] = 'Button 1'
self.button1.Bind(wx.EVT_BUTTON, self.buttonClick)
and so on for 50 buttons (or whatever) [they might be better created in a loop, btw;-)].
So buttonClick
becomes:
def buttonClick(self,event):
button_name = self.thebuttons.get(event.Id, '?No button?')
self.setTitle(button_name + ' clicked')
Solution 5
You could create a dictionary of buttons, and do the look based on the id
... something like this:
class MyFrame(wx.Frame):
def _add_button (self, *args):
btn = wx.Button (*args)
btn.Bind (wx.EVT_BUTTON, self.buttonClick)
self.buttons[btn.id] = btn
def __init__ (self):
self.button = dict ()
self._add_button (self.panel1, id=-1,
pos=(10, 20), size = (20,20))
self._add_button = (self.panel1, id=-1,
pos=(40, 20), size = (20,20))
self.Show (True)
def buttonClick(self,event):
self.SetTitle (self.buttons[event.Id].label)
JcMaco
Updated on June 04, 2022Comments
-
JcMaco almost 2 years
In the following code (inspired by this snippet), I use a single event handler
buttonClick
to change the title of the window. Currently, I need to evaluate if the Id of the event corresponds to the Id of the button. If I decide to add 50 buttons instead of 2, this method could become cumbersome. Is there a better way to do this?import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, wx.ID_ANY, 'wxBitmapButton', pos=(300, 150), size=(300, 350)) self.panel1 = wx.Panel(self, -1) self.button1 = wx.Button(self.panel1, id=-1, pos=(10, 20), size = (20,20)) self.button1.Bind(wx.EVT_BUTTON, self.buttonClick) self.button2 = wx.Button(self.panel1, id=-1, pos=(40, 20), size = (20,20)) self.button2.Bind(wx.EVT_BUTTON, self.buttonClick) self.Show(True) def buttonClick(self,event): if event.Id == self.button1.Id: self.SetTitle("Button 1 clicked") elif event.Id == self.button2.Id: self.SetTitle("Button 2 clicked") application = wx.PySimpleApp() window = MyFrame() application.MainLoop()
-
FogleBird almost 15 yearsI often set attributes on widgets as well when I can't think of a better way.
-
tom10 almost 15 yearsNice approach and use of cool new Python functionality (2.5 is new for me anyway). I would often do the
lambda
version of this, thoughfunctools.partail
is certainly more clear and without the troublesome name binding issues. -
dw1 about 2 yearsCould do
name = event.GetEventObject().GetLabel()
. Thanks for showing the GetEventObject() function!