Лучший способ получить название кнопки, которая вызвала событие? - PullRequest
4 голосов
/ 10 июня 2009

В следующем коде (вдохновленном этим фрагментом) я использую один обработчик событий buttonClick для изменения заголовка окна. В настоящее время мне нужно оценить, соответствует ли идентификатор события идентификатору кнопки. Если я решу добавить 50 кнопок вместо 2, этот метод может стать громоздким. Есть ли лучший способ сделать это?

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

Ответы [ 7 ]

10 голосов
/ 10 июня 2009

Вы можете присвоить кнопке имя, а затем посмотреть на имя в обработчике событий.

Когда вы делаете кнопку

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

При нажатии кнопки:

def OnClick(self, event):
    name = event.GetEventObject().myname
7 голосов
/ 11 июня 2009

Воспользуйтесь тем, что вы можете сделать на таком языке, как Python. Вы можете передать дополнительные аргументы вашей функции обратного вызова, например, так.

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

Конечно, аргументы могут быть любыми.

7 голосов
/ 10 июня 2009

Я рекомендую использовать разные обработчики событий для обработки событий от каждой кнопки. Если есть много общего, вы можете объединить это в функцию, которая возвращает функцию с нужным вам поведением, например:

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"
3 голосов
/ 10 июня 2009

Сохраняйте dict с ключами, которые являются .Id кнопок и значений, которые являются именами кнопок или чем-то еще, поэтому вместо длинной цепочки if/elif вы выполняете один dict поиск в buttonClick .

Фрагменты кода: в __init__, добавьте создание и обновление 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)

и т. Д. Для 50 кнопок (или чего-то еще) [они могут быть лучше созданы в цикле, кстати ;-)]. Так buttonClick становится:

   def buttonClick(self,event):
       button_name = self.thebuttons.get(event.Id, '?No button?')
       self.setTitle(button_name + ' clicked')
1 голос
/ 10 июня 2009

Вы можете создать словарь кнопок и выполнить поиск на основе id ... примерно так:

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)
0 голосов
/ 24 июня 2009

Мне нужно было сделать то же самое, чтобы отслеживать нажатия кнопок. Я использовал лямбда-функцию для привязки к событию. Таким образом, я мог передать весь объект кнопки в функцию-обработчик событий для соответствующей манипуляции.

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

Отказ от ответственности: это мой первый пост в stackoverflow

0 голосов
/ 10 июня 2009

Я столкнулся с аналогичной проблемой: я генерировал кнопки на основе предоставленных пользователем данных, и мне нужно было, чтобы кнопки влияли на другой класс, поэтому мне нужно было передать информацию о нажатии кнопки. Я явно назначил идентификаторы кнопок каждой сгенерированной кнопке, а затем сохранил информацию о них в словаре для последующего поиска.

Я бы подумал, что был бы более красивый способ сделать это, создав пользовательское событие, передающее больше информации, но все, что я видел, это метод поиска по словарю. Кроме того, я держу список кнопок, чтобы при необходимости все их можно было стереть.

Вот пример слегка вычищенного кода:

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