5

New python programmer here and trying to learn how to dynamically update widgets. To start, I have the following code. What I would like to do is change my variable "self.dynamiclength" to any integer, and have WxPython update the number of widgets appropriately. I have tried putting self.Refresh() and self.Update() in my TestFrame after updating self.dynamiclength to no avail.

I have done as much reading as possible on this before resorting to asking for help, but I am just too new at Wx to solve this one on my own. Thank you much!

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()
1
  • Note that I can figure out how to self.scrolling_window.Destroy(), but the problem is that I can't re–create scrolling_window, as I get sizer or a sort of binding error. Commented Apr 29, 2012 at 1:23

2 Answers 2

5

I have similar test code which I have written some time ago. Maybe you will find it useful.

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()
Sign up to request clarification or add additional context in comments.

1 Comment

self.GetParent().Fit() refresh the screen! or use self.GetParent().Layout(), the point is using self.GetParent() to get parent object, then call refresh on it.
3

If you need to update the number of widgets AFTER you've already created and shown the application, the you'll need to do it in a method, NOT in the init. The init only runs the first time the application is instantiated. Whenever you add or remove widgets after the frame is shown, you'll need to call Layout() on the parent widget or its sizer. See also

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.