如何定期刷新包含多个小部件的 wxPython 面板
how to refresh periodically a panel wxPython including several widgets
我正在使用 wxPython 制作的 GUI 设计一个应用程序。
它基本上有一个嵌入带有许多选项卡的笔记本的框架。
每个选项卡都是一个面板 class。
例如,在一个选项卡上,我有一个 ObjectListView 小部件和一些 pyplot 图。
随着数据在后台更新,我希望每 x 毫秒刷新一次完整选项卡。
正确的方法是什么?刷新整个面板或单独刷新每个小部件?
面板 class 是否应该像您对线程所做的那样包含 while True ?或使用事件?
如果有人可以突出显示这一点或将我指向指示如何执行此操作的网页,那将非常有帮助。
我想我没有使用正确的关键字进行搜索,因为我没有找到关于如何管理它的真正合适的描述....
谢谢
斯蒂芬
如果要绘制某些东西,您必须创建一个 Timer 对象并覆盖 OnPaint 事件。将 Timer 对象绑定到更新方法,这将被定期调用,每秒调用 60 次 (1/60)。我将粘贴在我的旧代码下方,该代码在左上角绘制了一个圆圈。如果您按下移动按钮,圆圈将沿对角线移动到右下方。
所以我想如果它适用于一个面板,它也应该适用于多个面板。
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()
我正在使用 wxPython 制作的 GUI 设计一个应用程序。 它基本上有一个嵌入带有许多选项卡的笔记本的框架。 每个选项卡都是一个面板 class。 例如,在一个选项卡上,我有一个 ObjectListView 小部件和一些 pyplot 图。 随着数据在后台更新,我希望每 x 毫秒刷新一次完整选项卡。
正确的方法是什么?刷新整个面板或单独刷新每个小部件?
面板 class 是否应该像您对线程所做的那样包含 while True ?或使用事件? 如果有人可以突出显示这一点或将我指向指示如何执行此操作的网页,那将非常有帮助。 我想我没有使用正确的关键字进行搜索,因为我没有找到关于如何管理它的真正合适的描述....
谢谢 斯蒂芬
如果要绘制某些东西,您必须创建一个 Timer 对象并覆盖 OnPaint 事件。将 Timer 对象绑定到更新方法,这将被定期调用,每秒调用 60 次 (1/60)。我将粘贴在我的旧代码下方,该代码在左上角绘制了一个圆圈。如果您按下移动按钮,圆圈将沿对角线移动到右下方。 所以我想如果它适用于一个面板,它也应该适用于多个面板。
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()