2017-05-04 133 views
0

我是新的使用wxPython,我想在某些面板(Panel1)显示时执行while循环,并在面板隐藏时停止它。如何在显示wx.panel时执行while循环?

我对循环感兴趣,因为我想更改Panel1中的标签值。

我试图从字面上把代码while True: ...,但没有工作,

有什么建议?

+2

你最好打赌就是开始一个线程,做你想要的东西。检查关于MT的wxPython演示。 – Igor

+2

根据你实际需要,一个计时器可能就够了。在wiki.wxpython.org上查找非阻塞GUI或LongRunningTasks。 –

回答

0

正如其他人所说的,你可以使用一个线程或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赶关闭事件,以确保退出应用程序,或者你可以有你的应用程序挂起或行为异常时,该线程停止。

+0

谢谢!它运作良好。我完全忘记了线程。再次感谢 :) –