[ACCEPTED]-Best way to get the name of a button that called an event?-wxpython
You could give the button a name, and then 2 look at the name in the event handler.
When 1 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
Take advantage of what you can do in a language 4 like Python. You can pass extra arguments 3 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 2 course, the arguments can be anything you 1 want.
I recommend that you use different event 4 handlers to handle events from each button. If 3 there is a lot of commonality, you can combine 2 that into a function which returns a function with 1 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"
Keep a dict
with keys that are the .Id
of the buttons 7 and values that are the button names or 6 whatever, so instead of a long if/elif
chain you 5 do a single dict
lookup in buttonClick
.
Code snippets: in 4 __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 3 on for 50 buttons (or whatever) [they might 2 be better created in a loop, btw;-)].
So 1 buttonClick
becomes:
def buttonClick(self,event):
button_name = self.thebuttons.get(event.Id, '?No button?')
self.setTitle(button_name + ' clicked')
You could create a dictionary of buttons, and 2 do the look based on the id
... something 1 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)
I ran into a similar problem: I was generating 13 buttons based on user-supplied data, and 12 I needed the buttons to affect another class, so 11 I needed to pass along information about 10 the buttonclick. What I did was explicitly 9 assign button IDs to each button I generated, then 8 stored information about them in a dictionary 7 to lookup later.
I would have thought there 6 would be a prettier way to do this, constructing 5 a custom event passing along more information, but 4 all I've seen is the dictionary-lookup method. Also, I 3 keep around a list of the buttons so I can 2 erase all of them when needed.
Here's a slightly 1 scrubbed code sample of something similar:
self.buttonDefs = {}
self.buttons = []
id_increment = 800
if (row, col) in self.items:
for ev in self.items[(row, col)]:
id_increment += 1
#### Populate a dict with the event information
self.buttonDefs[id_increment ] = (row, col, ev['user'])
####
tempBtn = wx.Button(self.sidebar, id_increment , "Choose",
(0,50+len(self.buttons)*40), (50,20) )
self.sidebar.Bind(wx.EVT_BUTTON, self.OnShiftClick, tempBtn)
self.buttons.append(tempBtn)
def OnShiftClick(self, evt):
### Lookup the information from the dict
row, col, user = self.buttonDefs[evt.GetId()]
self.WriteToCell(row, col, user)
self.DrawShiftPicker(row, col)
I needed to do the same thing to keep track 6 of button-presses . I used a lambda function 5 to bind to the event . That way I could 4 pass in the entire button object to the 3 event handler function to manipulate accordingly.
class PlatGridderTop(wx.Frame):
numbuttons = 0
buttonlist = []
def create_another_button(self, event): # wxGlade: PlateGridderTop.<event_handler>
buttoncreator_id = wx.ID_ANY
butonname = "button" + str(buttoncreator_id)
PlateGridderTop.numbuttons = PlateGridderTop.numbuttons + 1
thisbutton_number = PlateGridderTop.numbuttons
self.buttonname = wx.Button(self,buttoncreator_id ,"ChildButton %s" % thisbutton_number )
self.Bind(wx.EVT_BUTTON,lambda event, buttonpressed=self.buttonname: self.print_button_press(event,buttonpressed),self.buttonname)
self.buttonlist.append(self.buttonname)
self.__do_layout()
print "Clicked plate button %s" % butonname
event.Skip()
def print_button_press(self,event,clickerbutton):
"""Just a dummy method that responds to a button press"""
print "Clicked a created button named %s with wxpython ID %s" % (clickerbutton.GetLabel(),event.GetId())
Disclaimer 2 : This is my first post to stackoverflow 1
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.