Search code examples
wxpythonrefresh

how to refresh periodically a panel wxPython including several widgets


I'm designing an application with a GUI made with wxPython. It has basically a frame embedding a notebook with many tabs. Each tab is a panel class. For instance on one tab I've an ObjectListView widget and some pyplot graphs. I'd like to have the full tab refreshed every x milliseconds as the data are updated in background.

What is the proper way ? Refreshing the full panel or individually each widget ?

Shall a panel class include a while True like you would do for a thread ? or using events ? If anyone could highlight this or point me to a webpage indicating how to do that would be very helpful. I guess I'm not searching with the correct keywords as I don't find really suitable descriptions on how to manage this....

Thanks Stephane


Solution

  • You have to create a Timer object and also overwrite the OnPaint event if you want to draw something. Bind the Timer object to an update method, this will be called periodically, 60 times in a second (1/60). I will paste below an old code of mine which draws a circle in the upper left corner. If you press the Move button, the circle will move diagonally to the lower right. So I guess if it works on one Panel, it should also work with multiple Panels.

    import wx
    
    
    class MyPanel(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent)
    
            self.Bind(wx.EVT_PAINT, self.OnPaint)
    
            # create a timer
            self.timer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER, self.update, self.timer)
    
            # start x, y position of the circle
            self.x, self.y = 0, 0
            # refresh rate
            self.delta = 1/60
    
            self.SetDoubleBuffered(True)
    
            btn1 = wx.Button(self, wx.ID_ANY, u"Move", size=(100, 50), pos=(800, 100))
            self.Bind(wx.EVT_BUTTON, self.start_simulation, btn1)
    
        def start_simulation(self, evt):
            self.timer.Start(self.delta)
    
        def OnPaint(self, event):
            dc = wx.PaintDC(self)
    
            dc.SetBrush(wx.Brush('#c56c00'))
            dc.DrawEllipse(self.x, self.y, 60, 60)
    
            # dc.DrawEllipse(0, 20, 60, 60)
            dc.DrawLine(0, 600, 800, 600)
    
        def update(self, evt):
            self.x += 2
            self.y += 2
            self.Refresh()
    
    
    class MyFrame(wx.Frame):
        def __init__(self):
            self.size = (1280, 720)
            super().__init__(None, title="Moving circle", size=self.size, style=wx.DEFAULT_FRAME_STYLE)
    
            self.panel = MyPanel(self)
    
    
    class MyApp(wx.App):
        def OnInit(self):
            frame = MyFrame()
            frame.Show()
            return True
    
    
    if __name__ == "__main__":
        app = MyApp()
        app.MainLoop()