wxpython中添加和删除按钮的简单示例

A simple example for adding and removing buttons in wxpython

我正在使用 wxpython。

我想为包含按钮 "Add" 的 GUI 解决一个简单的问题,当按下该按钮时会创建一个名为 "Remove" 的新按钮。您可以按 "Add" 任意多次,并且会创建许多删除按钮并将其添加到面板中。 我想要的是当您按下其中一个删除按钮时,删除按钮本身会从面板中删除。

问题是当你将一个函数绑定到一个按钮时:

self.Bind(wx.EVT_BUTTON, self.remove_function, button_name)

您不能将参数传递给函数来告诉它要删除哪个按钮。 (或者你可以吗?)

几年前我在这里写过这个话题:

以下示例可能有所帮助:

import wx

########################################################################
class MyPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        self.btns = 1

        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
        add_btn = wx.Button(self, label='Add')
        add_btn.Bind(wx.EVT_BUTTON, self.add_button)

        self.main_sizer.Add(add_btn, 0, wx.CENTER|wx.ALL, 5)
        self.SetSizer(self.main_sizer)

    #----------------------------------------------------------------------
    def add_button(self, event):
        """"""
        new_btn = wx.Button(self, label="Remove %s" % self.btns)
        new_btn.Bind(wx.EVT_BUTTON, self.remove_button)
        self.btns += 1
        self.main_sizer.Add(new_btn, 0, wx.CENTER|wx.ALL, 5)
        self.main_sizer.Layout()

    #----------------------------------------------------------------------
    def remove_button(self, event):
        """"""
        btn = event.GetEventObject()
        print "Deleting %s button" % btn.GetLabel()
        self.main_sizer.Hide(btn)
        self.main_sizer.Remove(btn)
        self.main_sizer.Layout()


########################################################################
class MyFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Buttons")
        panel = MyPanel(self)
        self.Show()

if __name__ == '__main__':
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

您还可以使用 lambda、内联函数或 functools 传递按钮对象:

下面是有关将多个小部件绑定到同一事件处理程序的一些附加信息:

如果您的麻烦在于将参数传递给函数,请考虑以下操作:

self.Bind(wx.EVT_BUTTON, lambda e: otherFunction(arg1, arg2), button_name)

@Mike Driscoll 感谢您提供了很好的示例。不幸的是,它在 Python 3.9.2 中不能正常工作(不再?)。你的线路

self.main_sizer.Remove(btn)

在 remove_button() 方法中抛出 TypeError:

TypeError: Sizer.Remove(): arguments did not match any overloaded call:

overload 1: argument 1 has unexpected type 'Button'

overload 2: argument 1 has unexpected type 'Button'

对我来说,wx.Sizer.Remove() 只适用于 SizerItem 的索引。所以不要使用

self.main_sizer.Remove(btn)

我用过:

sizerItemIdx = 0

for sizerItem in self.main_sizer.GetChildren():
    widget = sizerItem.GetWindow()
    if widget == btn:
        self.main_sizer.Remove(sizerItemIdx)
    sizerItemIdx += 1

如果有更简单或更elegant/Pythonian的方法,请告诉我。