我是新的使用wxPython,我想在某些面板(Panel1)显示时执行while循环,并在面板隐藏时停止它。如何在显示wx.panel时执行while循环?
我对循环感兴趣,因为我想更改Panel1中的标签值。
我试图从字面上把代码while True: ...
,但没有工作,
有什么建议?
我是新的使用wxPython,我想在某些面板(Panel1)显示时执行while循环,并在面板隐藏时停止它。如何在显示wx.panel时执行while循环?
我对循环感兴趣,因为我想更改Panel1中的标签值。
我试图从字面上把代码while True: ...
,但没有工作,
有什么建议?
正如其他人所说的,你可以使用一个线程或wx.Timer
来完成你正在寻找的东西。我从旧的面板切换tutorial中抓取了一些代码,并修改它以显示如何使用计时器方法。你所要做的就是运行下面的代码并通过菜单切换面板:
import wx
import wx.grid as gridlib
########################################################################
class PanelOne(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
grid = gridlib.Grid(self)
grid.CreateGrid(25,12)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 0, wx.EXPAND)
self.SetSizer(sizer)
########################################################################
class PanelTwo(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
self.count = 0
self.lbl = wx.StaticText(self,
label='Counter: {}'.format(self.count))
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.update, self.timer)
#----------------------------------------------------------------------
def start_timer(self):
self.timer.Start(1000)
#----------------------------------------------------------------------
def stop_timer(self):
self.timer.Stop()
#----------------------------------------------------------------------
def update(self, event):
self.count += 1
self.lbl.SetLabel('Counter: {}'.format(self.count))
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
"Panel Switcher Tutorial")
self.panel_one = PanelOne(self)
self.panel_two = PanelTwo(self)
self.panel_two.Hide()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.panel_one, 1, wx.EXPAND)
self.sizer.Add(self.panel_two, 1, wx.EXPAND)
self.SetSizer(self.sizer)
menubar = wx.MenuBar()
fileMenu = wx.Menu()
switch_panels_menu_item = fileMenu.Append(wx.ID_ANY,
"Switch Panels",
"Some text")
self.Bind(wx.EVT_MENU, self.onSwitchPanels,
switch_panels_menu_item)
menubar.Append(fileMenu, '&File')
self.SetMenuBar(menubar)
#----------------------------------------------------------------------
def onSwitchPanels(self, event):
""""""
if self.panel_one.IsShown():
self.SetTitle("Panel Two Showing")
self.panel_one.Hide()
self.panel_two.Show()
self.panel_two.start_timer()
else:
self.SetTitle("Panel One Showing")
self.panel_one.Show()
self.panel_two.stop_timer()
self.panel_two.Hide()
self.Layout()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
就我个人而言,我认为使用这个线程是矫枉过正。不过,修改上面的代码来代替使用线程会很有趣。因此,这里的那个版本太:
import time
import wx
import wx.grid as gridlib
from threading import Thread
########################################################################
class TestThread(Thread):
"""Test Worker Thread Class."""
#----------------------------------------------------------------------
def __init__(self, panel):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.panel = panel
self.sentinel = True
self.start() # start the thread
#----------------------------------------------------------------------
def run(self):
"""Run Worker Thread."""
# This is the code executing in the new thread.
while self.sentinel:
time.sleep(1)
wx.CallAfter(self.panel.update)
print 'Thread finished!'
########################################################################
class PanelOne(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
grid = gridlib.Grid(self)
grid.CreateGrid(25,12)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 0, wx.EXPAND)
self.SetSizer(sizer)
########################################################################
class PanelTwo(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
self.count = 0
self.lbl = wx.StaticText(self,
label='Counter: {}'.format(self.count))
self.thread = None
#----------------------------------------------------------------------
def start_timer(self):
self.thread = TestThread(self)
#----------------------------------------------------------------------
def stop_timer(self):
self.thread.sentinel = False
#----------------------------------------------------------------------
def update(self):
self.count += 1
self.lbl.SetLabel('Counter: {}'.format(self.count))
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
"Panel Switcher Tutorial")
self.panel_one = PanelOne(self)
self.panel_two = PanelTwo(self)
self.panel_two.Hide()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.panel_one, 1, wx.EXPAND)
self.sizer.Add(self.panel_two, 1, wx.EXPAND)
self.SetSizer(self.sizer)
menubar = wx.MenuBar()
fileMenu = wx.Menu()
switch_panels_menu_item = fileMenu.Append(wx.ID_ANY,
"Switch Panels",
"Some text")
self.Bind(wx.EVT_MENU, self.onSwitchPanels,
switch_panels_menu_item)
self.Bind(wx.EVT_CLOSE, self.on_close)
menubar.Append(fileMenu, '&File')
self.SetMenuBar(menubar)
#----------------------------------------------------------------------
def onSwitchPanels(self, event):
""""""
if self.panel_one.IsShown():
self.SetTitle("Panel Two Showing")
self.panel_one.Hide()
self.panel_two.Show()
self.panel_two.start_timer()
else:
self.SetTitle("Panel One Showing")
self.panel_one.Show()
self.panel_two.stop_timer()
self.panel_two.Hide()
self.Layout()
#----------------------------------------------------------------------
def on_close(self, event):
self.panel_two.stop_timer()
self.panel_two.thread.join()
self.Destroy()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
需要注意的是,你会希望通过EVT_CLOSE
赶关闭事件,以确保退出应用程序,或者你可以有你的应用程序挂起或行为异常时,该线程停止。
谢谢!它运作良好。我完全忘记了线程。再次感谢 :) –
你最好打赌就是开始一个线程,做你想要的东西。检查关于MT的wxPython演示。 – Igor
根据你实际需要,一个计时器可能就够了。在wiki.wxpython.org上查找非阻塞GUI或LongRunningTasks。 –