动态更新/刷新创建的WxPython小部件

5

我是一名新的Python程序员,正在努力学习如何动态更新小部件。首先,我有以下代码。我想做的是将我的变量“self.dynamiclength”更改为任何整数,并让WxPython相应地更新小部件的数量。我已经尝试在更新self.dynamiclength后在TestFrame中放置self.Refresh()和self.Update(),但没有成功。

在寻求帮助之前,我已经尽可能多地阅读了相关内容,但我对Wx还太生疏了,无法自己解决这个问题。非常感谢您的帮助!

import wx
import  wx.lib.scrolledpanel as scrolled

class TestFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, size=(1000, 550))
        panel = wx.Panel(self)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        pbox0 = wx.BoxSizer(wx.VERTICAL)
        controlback0 = wx.Button(panel, label="Back0")
        controlforward0 = wx.Button(panel, label="Forward0")
        pbox0.Add(controlback0, 0, wx.ALL)
        pbox0.Add(controlforward0, 0, wx.ALL)
        mainSizer.Add(pbox0)

        self.scrolling_window = scrolled.ScrolledPanel( panel )
        self.scrolling_window.SetAutoLayout(1)
        self.scrolling_window.SetupScrolling()
        self.sizer = wx.BoxSizer( wx.VERTICAL )
        self.child_windows = []

        ##############################################
        #this is the variable that I want to change, 
        #and I don't know how to get the 'for loop' 
        #below to update as well. 

        self.eedictionary = {}
        self.dynamiclength = 5
        for i in range(0,self.dynamiclength):
            wind = self.addBox(i)
            self.sizer.Add(wind, 0, wx.CENTER|wx.ALL, 5)
        ###############################################
        #the following code binds all appropriate buttons to a pedigree variable updater
        button_binding_list = ['controlback','controlforward']
        for j in button_binding_list:
            eid = self.eedictionary[str(i)+j]
            self.scrolling_window.Bind(wx.EVT_BUTTON, lambda evt: self.onclick(evt, id), id=eid)

        self.scrolling_window.SetSizer(self.sizer)

        mainSizer.Add(self.scrolling_window, 1, wx.EXPAND)
        panel.SetSizer(mainSizer)

    def addBox(self, i):
        pbox = wx.BoxSizer(wx.VERTICAL)

        controlback = wx.Button(self.scrolling_window, label="Back")
        controlforward = wx.Button(self.scrolling_window, label="Forward")

        pbox.AddMany([(controlback, 0, wx.ALL), (controlforward, 0, wx.ALL)])

        #for each object created in the addBox module, its id is added to the dictionary 
        self.eedictionary[str(i)+'controlback'] = controlback.GetId()
        self.eedictionary[str(i)+'controlforward'] = controlforward.GetId()
        return pbox

    def onclick(self, event):
        self.dynamiclength +=1
        print 'added one to self.dynamiclength', self.dynamiclength

if __name__=='__main__':
    app = wx.App(False)
    f = TestFrame()
    f.Show()
    app.MainLoop()

请注意,我可以强制销毁self.scrolling_window,但问题是我无法重新创建scrolling_window,因为我会遇到sizer或绑定错误。 - mh00h
2个回答

5

我有类似的测试代码,是我一段时间以前写的。也许你会觉得它有用。

import wx

#===================================================================================================
class UpperPanel(wx.Panel):
    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)
        self.combo = wx.ComboBox(self, choices=["0", "1", "2", "3", "4"], size=(200, -1))
        self.combo.Bind(wx.EVT_COMBOBOX, self.GetParent().middlePanel.Change)
        self.logo = wx.Button(self, size=(300, 100))

        self.sizer = wx.BoxSizer()
        self.sizer.Add(self.combo, 0, wx.EXPAND)
        self.sizer.Add(self.logo, 0, wx.EXPAND)

        self.SetSizerAndFit(self.sizer)

#===================================================================================================
class MiddlePanel(wx.Panel):
    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)
        self.subs = []
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizerAndFit(self.sizer)


    def Change(self, e):
        self.sizer = wx.BoxSizer(wx.VERTICAL)

        for a in self.subs:
            a.Destroy()

        self.subs = []

        for a in range(int(e.GetString())):
            b = wx.Button(self, size=(-1, 50))
            self.subs.append(b)
            self.sizer.Add(b, 1, wx.EXPAND)

        self.SetSizerAndFit(self.sizer)
        self.GetParent().Fit()

#===================================================================================================
class MainWin(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)

        self.middlePanel = MiddlePanel(self)
        self.upperPanel = UpperPanel(self)
        self.textArea = wx.TextCtrl(self, size=(-1, 300), style=wx.TE_MULTILINE)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.upperPanel, 0, wx.EXPAND)
        self.sizer.Add(self.middlePanel, 0, wx.EXPAND)
        self.sizer.Add(self.textArea, 1, wx.EXPAND)

        self.SetSizerAndFit(self.sizer)

#===================================================================================================
if __name__ == '__main__':
    app = wx.PySimpleApp()
    main_win = MainWin()
    main_win.Show()
    app.MainLoop()

self.GetParent().Fit() 刷新屏幕!或者使用 self.GetParent().Layout(),重点是使用 self.GetParent() 获取父对象,然后在其上调用刷新。 - allenyllee

3
如果您需要在已经创建并显示应用程序之后更新小部件的数量,则需要在方法中而不是 init 中进行。 init 只在实例化应用程序时运行一次。每当您在显示框架后添加或删除小部件时,都需要在父小部件或其大小调整器上调用 Layout()。另请参见:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接