获取调用事件的按钮名称的最佳方法是什么?

时间:2009-06-10 15:34:44

标签: python user-interface events event-handling wxpython

在以下代码中(受this代码段启发),我使用单个事件处理程序buttonClick来更改窗口的标题。目前,我需要评估事件的Id是否与按钮的Id相对应。如果我决定添加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 个答案:

答案 0 :(得分:10)

您可以为按钮指定名称,然后查看事件处理程序中的名称。

当您按下

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

答案 1 :(得分:7)

我建议您使用不同的事件处理程序来处理每个按钮的事件。如果有很多共性,你可以将它组合成一个函数,返回一个具有你想要的特定行为的函数,例如:

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"

答案 2 :(得分:7)

利用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

当然,争论可以是你想要的任何东西。

答案 3 :(得分:3)

使用按键的dict和按钮名称或其他值的键保留.Id,所以不要使用长if/elif链来执行单dict buttonClick 1}}在__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) 的创建和更新:

buttonClick

依此类推50个按钮(或其他任何东西)[它们可能更好地在循环中创建,btw ;-)]。 所以 def buttonClick(self,event): button_name = self.thebuttons.get(event.Id, '?No button?') self.setTitle(button_name + ' clicked') 变为:

{{1}}

答案 4 :(得分:1)

您可以创建一个按钮字典,并根据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)

答案 5 :(得分:0)

我遇到了类似的问题:我根据用户提供的数据生成按钮,我需要按钮来影响另一个类,所以我需要传递有关buttonclick的信息。我所做的是明确地为我生成的每个按钮分配按钮ID,然后将它们存储在字典中以便稍后查找。

我原本以为会有更漂亮的方法来构建一个传递更多信息的自定义事件,但我所看到的只是字典查找方法。另外,我保留了按钮列表,以便在需要时删除所有按钮。

这是一个略微擦除的类似代码示例:

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)

答案 6 :(得分:0)

我需要做同样的事情来跟踪按钮按下。我使用lambda函数绑定到事件。这样我就可以将整个按钮对象传递给事件处理函数来进行相应的操作。

    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的文章