user1236097
user1236097

Reputation: 303

What is the recommended way to redraw wxframe content?

I have a wx.Frame. I need to change the content from time to time. I have a timer and every few seconds I check the state, and if the state has been changed, I need to change the content of the frame.

In order to do this, I created a panel in the frame called panel.Reparent(None), and created a panel with new content, but the frame is not updated with the newly created panel. I tried with destroy (panel.Destroy()) but this didn't work.

What is the recommended way to change frame content (not only data, I need to add and remove UI components)?

class TestFrame(wx.Frame): def init(self): wx.Frame.init(self, None, title="Double Buffered Drawing") self.counter = 0 self.panel = wx.Panel(self, -1) wx.CheckBox(self.panel, -1, "Alpha", (35, 40), (150, 20))

    # Create a timer to update the data values
    self.Bind(wx.EVT_TIMER, self.OnTimeout)
    self.timer = wx.Timer(self)
    self.timer.Start(5000)


def OnTimeout(self, evt):
    p  = self.panel
    self.counter = self.counter + 1
    try:
        p.Reparent(None)
    except e:
        print 'B'
    if self.counter % 2 == 0:
       self.panel = wx.Panel(self, -1)
       wx.CheckBox(self.panel, -1, "Alpha", (35, 40), (150, 20))
       self.Show()  #Tried also self.Layout self.Refresh self.Update

Upvotes: 0

Views: 2742

Answers (1)

Mike Driscoll
Mike Driscoll

Reputation: 33111

When adding or removing widgets during run time, you almost always have to call Layout() after the removal or addition of a widget. Usually calling Layout on the parent sizer will do the trick, but sometimes you have to call it on the frame object. You can see one example here where I just hid one panel and showed another.

I also wrote another tutorial on actually removing or adding widgets dynamically. That might help you too.

EDIT (6-26-12): Since the OP seems to require an example, I wrote a self-destructing panel:

import wx

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

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

        self.countdown = wx.StaticText(self, label="This panel will self-destruct in 10 seconds")


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

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

        txt = wx.StaticText(self, label="Panel Two")


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

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Panel Smacker")
        self.panelOne = PanelOne(self)
        self.time2die = 10

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.update, self.timer)
        self.timer.Start(1000)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.panelOne, 1, wx.EXPAND)
        self.SetSizer(self.sizer)

    #----------------------------------------------------------------------
    def update(self, event):
        """"""
        if self.time2die < 0:
            self.panelOne.Destroy()
            self.panelTwo = PanelTwo(self)
            self.sizer.Add(self.panelTwo, 1, wx.EXPAND)
            self.Layout()
            self.timer.Stop()
        else:
            msg = "This panel will self-destruct in %s seconds" % self.time2die
            self.panelOne.countdown.SetLabel(msg)
        self.time2die -= 1

if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

Upvotes: 1

Related Questions