geekdoc-python-zh/docs/pythonlibrary/wxpython-adding-and-removin...

5.0 KiB
Raw Permalink Blame History

wxPython:动态添加和移除小部件

原文:https://www.blog.pythonlibrary.org/2012/05/05/wxpython-adding-and-removing-widgets-dynamically/

我不断看到有人在启动 wxPython 应用程序后询问如何添加或删除小部件。这实际上是很容易做到的事情,所以我决定是时候写一个关于这个主题的简单教程了。我不得不根据访问我的程序的用户类型自己不时地这样做,这样我就可以显示稍微不同的选项。不管怎样,我们开始吧!

我决定让事情变得简单。这个应用程序所做的就是允许用户添加或删除按钮。下面的脚本将创建一个类似于本文开头的窗口。如果您按几次“添加”按钮,您应该会看到类似这样的内容:

正如你所看到的,你最终得到了更多的按钮!现在让我们花一点时间来阅读代码。你一读完我就解释。

import wx

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

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        self.number_of_buttons = 0
        self.frame = parent

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        controlSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.widgetSizer = wx.BoxSizer(wx.VERTICAL)

        self.addButton = wx.Button(self, label="Add")
        self.addButton.Bind(wx.EVT_BUTTON, self.onAddWidget)
        controlSizer.Add(self.addButton, 0, wx.CENTER|wx.ALL, 5)

        self.removeButton = wx.Button(self, label="Remove")
        self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveWidget)
        controlSizer.Add(self.removeButton, 0, wx.CENTER|wx.ALL, 5)

        self.mainSizer.Add(controlSizer, 0, wx.CENTER)
        self.mainSizer.Add(self.widgetSizer, 0, wx.CENTER|wx.ALL, 10)

        self.SetSizer(self.mainSizer)

    #----------------------------------------------------------------------
    def onAddWidget(self, event):
        """"""
        self.number_of_buttons += 1
        label = "Button %s" %  self.number_of_buttons
        name = "button%s" % self.number_of_buttons
        new_button = wx.Button(self, label=label, name=name)
        self.widgetSizer.Add(new_button, 0, wx.ALL, 5)
        self.frame.fSizer.Layout()
        self.frame.Fit()

    #----------------------------------------------------------------------
    def onRemoveWidget(self, event):
        if self.widgetSizer.GetChildren():
            sizer_item = self.widgetSizer.GetItem(self.number_of_buttons-1)
            widget = sizer_item.GetWindow()
            self.widgetSizer.Hide(widget)
            widget.Destroy()
            self.number_of_buttons -= 1
            self.frame.fSizer.Layout()
            self.frame.Fit()

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

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, parent=None, title="Add / Remove Buttons")
        self.fSizer = wx.BoxSizer(wx.VERTICAL)
        panel = MyPanel(self)
        self.fSizer.Add(panel, 1, wx.EXPAND)
        self.SetSizer(self.fSizer)
        self.Fit()
        self.Show()

#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

我认为这是非常简单的代码,所以我们只关注重要的部分。我要指出的第一个主题是,我在显示它之前调用了框架的 Fit()方法。我通常避免使用 Fit但每当我添加或删除按钮时我很难让框架适当地改变大小Fit 为我解决了这个问题。我应该注意到Fit 总是试图让窗口小部件适合容器,有时它以我不喜欢的方式结束了。

总之onAddWidget 和 onRemoveWidget 方法中的另一位。您通常希望在容器对象上调用 Layout以便每当您添加或移除小部件时它都可以更新和布局控件。奇怪的是Fit 似乎会自动这样做,所以您在上面的代码中看到的那些 Layout()调用实际上可以被删除。我试着去掉合适的,看看布局是否足够,但当你这样做时,框架不会更新它的大小,所以在这种情况下,合适似乎是必需的。现在,如果你碰巧添加或删除了一些小部件,而不会影响框架的整体大小,我认为布局就足够了。

最后,顺便提一下,有时在冻结/解冻更新的结尾也使用 Layout()。

好吧,就这样!现在,您也应该能够在应用程序运行后添加或删除小部件了。我希望你学到了新东西。