Best way to get the name of a button called an event?

In the following code (inspired by this snippet), I use a single buttonClick event handler to change the window title. Currently I need to evaluate if the event Id matches the button id. If I decide to add 50 buttons instead of 2, this method can 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() 
+4
source share
7 answers

You can give the button a name, and then look at the name in the event handler.

When you make a button

 b = wx.Button(self, 10, "Default Button", (20, 20)) b.myname = "default button" self.Bind(wx.EVT_BUTTON, self.OnClick, b) 

At the push of a button:

 def OnClick(self, event): name = event.GetEventObject().myname 
+10
source

I recommend that you use different event handlers to handle events with each button. If there is a lot in common, you can combine this into a function that returns a function with the specific behavior you want, for example:

 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" 
+7
source

Take advantage of what you can do in Python. You can pass additional arguments to the event callback function, for example.

 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 whatever you want.

+7
source

Save the dict with the .Id keys of the buttons and the values, which are the names of the buttons or something else, so instead of a long chain of if/elif you do a single dict search in buttonClick .

Code snippets: in __init__ add create and update 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) 

etc. for 50 buttons (or something else) [they can be better created in a loop, btw ;-)]. Therefore buttonClick becomes:

  def buttonClick(self,event): button_name = self.thebuttons.get(event.Id, '?No button?') self.setTitle(button_name + ' clicked') 
+3
source

You can create a dictionary of buttons and make a look based on 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) 
+1
source

I had a similar problem: I generated buttons based on the data provided by the user, and I need the buttons to affect another class, so I needed to pass the information about the button buttonclick. What I did was explicitly assign the button identifiers to each generated button, and then store the information about them in a dictionary for search later.

I would have thought that there would be a more beautiful way to do this by creating a custom event that goes through additional information, but all I saw was a dictionary search method. In addition, I keep a list of buttons, so I can delete them all when necessary.

Here's a slightly cleaned up code example 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) 
0
source

I needed to do the same to track button clicks. I used the lambda function to bind to an event. That way, I could pass the entire button object to an 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: This is my first post on stackoverflow

0
source

Source: https://habr.com/ru/post/1286021/


All Articles