2017-05-04 1 views
0

Je suis nouveau en utilisant wxPython et je veux exécuter une boucle while juste quand un certain panneau (Panel1) est montré et l'arrêter quand le panneau est caché.Comment exécuter une boucle while lorsque wx.panel est affiché?

Je suis intéressé par la boucle parce que je veux changer la valeur d'une étiquette qui est dans le Panel1.

J'ai essayé de mettre littéralement le code while True: ..., mais ne fonctionne pas,

Toutes les suggestions?

+2

votre meilleur pari sera de commencer un fil et faire ce que vous voulez à l'intérieur. Vérifiez la démo wxPython sur le MT. – Igor

+2

En fonction de ce dont vous avez réellement besoin, une minuterie peut être juste suffisante. Recherchez l'interface graphique non bloquante ou LongRunningTasks sur wiki.wxpython.org. –

Répondre

0

Comme les autres l'ont mentionné, vous pouvez utiliser un thread ou un wx.Timer pour accomplir ce que vous cherchez. J'ai attrapé du code de mon ancien panneau en changeant tutorial et l'ai modifié pour montrer comment utiliser l'approche du minuteur. Tout ce que vous devez faire est de lancer le code suivant et commuter les panneaux via le menu:

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() 

Personnellement, je pense que l'aide d'un fil pour cela est exagéré. Cependant, il était amusant de modifier le code ci-dessus pour utiliser un thread à la place. Voici donc cette version aussi:

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() 

Notez que vous voulez attraper l'événement près par EVT_CLOSE pour vous assurer que le fil est arrêté lorsque vous quittez votre application ou vous pouvez avoir votre application ou se conduisent mal accrocher.

+0

Merci! Cela a bien fonctionné. J'ai complètement oublié les discussions. Merci encore :) –