¿La mejor manera de obtener el nombre de un botón que llama un evento?

En el siguiente código (inspirado en este fragmento de código), uso un solo buttonClick controlador de buttonClick para cambiar el título de la ventana. Actualmente, necesito evaluar si la Id. Del evento corresponde a la Id del botón. Si decido agregar 50 botones en lugar de 2, este método podría volverse incómodo. ¿Hay una mejor manera de hacer esto?

 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() 

Podría darle un nombre al botón y luego mirar el nombre en el controlador de eventos.

Cuando haces el boton

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

Cuando se hace clic en el botón:

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

Le recomiendo que use diferentes controladores de eventos para manejar los eventos de cada botón. Si hay muchos puntos en común, puede combinar eso en una función que devuelva una función con el comportamiento específico que desea, por ejemplo:

 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" 

Aproveche lo que puede hacer en un lenguaje como Python. Puede pasar argumentos adicionales a su función de callback de evento, como así.

 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 

Por supuesto, los argumentos pueden ser lo que quieras.

Mantenga un dict con las teclas que son el .Id de los botones y los valores que son los nombres de los botones o lo que sea, así que en lugar de una larga cadena de if/elif , haga una búsqueda de un solo buttonClick en el buttonClick .

__init__ código: en __init__ , agregue la creación y actualización del 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) 

y así sucesivamente para 50 botones (o lo que sea) [podrían crearse mejor en un bucle, por cierto ;-)]. Así que buttonClick convierte:

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

Podrías crear un diccionario de botones, y hacer el look basado en la id … algo como esto:

 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) 

Me encontré con un problema similar: estaba generando botones basados ​​en los datos proporcionados por el usuario, y necesitaba que los botones afectaran a otra clase, por lo que necesitaba transmitir información sobre el clic del botón. Lo que hice fue asignar explícitamente las identificaciones de los botones a cada botón que generé, y luego almacenar información sobre ellos en un diccionario para buscar más tarde.

Pensé que habría una forma más bonita de hacer esto, construyendo un evento personalizado que transmita más información, pero todo lo que he visto es el método de búsqueda en el diccionario. Además, guardo una lista de los botones para poder borrarlos todos cuando sea necesario.

Aquí hay un ejemplo de código ligeramente borrado de algo 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) 

Necesitaba hacer lo mismo para hacer un seguimiento de las pulsaciones de botones. Utilicé una función lambda para enlazar al evento. De esa manera, podría pasar todo el objeto del botón a la función del controlador de eventos para manipularlo en consecuencia.

  class PlatGridderTop(wx.Frame): numbuttons = 0 buttonlist = [] def create_another_button(self, event): # wxGlade: PlateGridderTop. 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()) 

Descargo de responsabilidad: Esta es mi primera publicación en stackoverflow