2014-03-12 37 views
1

我正在使用Windows 7 OS上的Python v2.7和wxPython v3.0的GUI應用程序。 我必須不斷更新我的GUI,其中包含許多面板。每個面板包含一個wx.StaticText。我必須不斷更新這些wx.StaticTexts。我想到了使用threads。此外,我正在使用pubsub模塊與GUI進行通信以更新這些wx.StaticTexts。每件事都按預期工作。 我已經在我的真正問題的下面創建了一個簡短的演示。使用線程在wxPython中不斷更新GUI的好方法?

問題:在我的代碼下面,創建了兩個線程。這兩個線程都可以使用wx.CallAfter()來更新GUI。如果我有100個面板要更新怎麼辦?我是否需要爲每個更新特定面板的線程創建100個類?我希望線程獨立於其他線程工作。 什麼可能是比這更好的方法?

代碼:請從下面的示例代碼中打轉轉:

import wx 
from wx.lib.pubsub import setupkwargs 
from wx.lib.pubsub import pub 
import time 
from threading import Thread 
import threading 

class GUI(wx.Frame): 
    def __init__(self, parent, id, title): 
     screenWidth = 500 
     screenHeight = 400 
     screenSize = (screenWidth,screenHeight) 
     wx.Frame.__init__(self, None, id, title, size=screenSize) 
     self.locationFont = locationFont = wx.Font(12, wx.MODERN, wx.NORMAL, wx.BOLD) 
     mainSizer = wx.BoxSizer(wx.VERTICAL) 
     myPanelA = wx.Panel(self, style=wx.SIMPLE_BORDER) 
     myPanelA.SetBackgroundColour('#C0FAE0') 
     self.myTextA = wx.StaticText(myPanelA, -1, "I have a problem :(") 
     myPanelB = wx.Panel(self, style=wx.SIMPLE_BORDER) 
     myPanelB.SetBackgroundColour('#C0FAFF') 
     self.myTextB = wx.StaticText(myPanelB, -1, "Me too :(") 
     mainSizer.Add(myPanelA, 1, wx.EXPAND, 5) 
     mainSizer.Add(myPanelB, 1, wx.EXPAND, 5) 
     self.SetSizer(mainSizer) 
     pub.subscribe(self.updatePanelA, 'Update-panelA') 
     pub.subscribe(self.updatePanelB, 'Update-panelB') 

    def updatePanelA(self, message): 
     self.myTextA.SetLabel(message) 

    def updatePanelB(self, message): 
     self.myTextB.SetLabel(message) 

class threadA(Thread): 
    def __init__(self): 
     Thread.__init__(self) 
     self.start() 
    def run(self): 
     ObjA = updateGUI() 
     ObjA.methodA() 

class threadB(Thread): 
    def __init__(self): 
     Thread.__init__(self) 
     self.start() 
    def run(self): 
     ObjB = updateGUI() 
     ObjB.methodB() 

class updateGUI(): 
    def methodA(self): 
     while True: 
      time.sleep(3) 
      wx.CallAfter(pub.sendMessage, 'Update-panelA', message='Problem solved') 
    def methodB(self): 
     while True: 
      time.sleep(5) 
      wx.CallAfter(pub.sendMessage, 'Update-panelB', message='Mine too') 

if __name__=='__main__': 
    app = wx.App() 
    frame = GUI(parent=None, id=-1, title="Problem Demo") 
    frame.Show() 
    threadA() 
    threadB() 
    app.MainLoop() 

謝謝您的時間!

回答

2

您可以定義您的私有「selfUpdatePanel」以啓動其自己的線程來更新其自己的文本字段。代碼將很容易以這種方式維護。

檢查下面的代碼基礎上改裝代碼:

import wx 
from wx.lib.pubsub import setupkwargs 
from wx.lib.pubsub import pub 
import time 
from threading import Thread 
import threading 


class selfUpdatePanel(wx.Panel): 
    def __init__(self, parent, mystyle, interval, topic, message): 
     wx.Panel.__init__(self, parent, style = mystyle) 
     pub.subscribe(self.updatePanel, topic) 
     self.updateMsg = message 
     self.textCtrl = None 
     self.interval = interval 
     self.topic = topic 
     pub.subscribe(self.updatePanel, self.topic) 

    def setTextCtrl(self,text): 
     self.textCtrl = text 

    def updatePanel(self): 
     self.textCtrl.SetLabel(self.updateMsg) 

    def threadMethod(self): 
     while True: 
      print "threadMethod" 
      time.sleep(self.interval) 
      wx.CallAfter(pub.sendMessage, self.topic) 

    def startThread(self): 
     self.thread = Thread(target=self.threadMethod) 
     self.thread.start() 


class GUI(wx.Frame): 
    def __init__(self, parent, id, title): 
     screenWidth = 500 
     screenHeight = 400 
     screenSize = (screenWidth,screenHeight) 
     wx.Frame.__init__(self, None, id, title, size=screenSize) 
     self.locationFont = locationFont = wx.Font(12, wx.MODERN, wx.NORMAL, wx.BOLD) 
     mainSizer = wx.BoxSizer(wx.VERTICAL) 
     #myPanelA = wx.Panel(self, style=wx.SIMPLE_BORDER) 

     myPanelA = selfUpdatePanel(self, wx.SIMPLE_BORDER, 3, 'Update-panelA', 'Problem solved') 
     myPanelA.SetBackgroundColour('#C0FAE0') 
     self.myTextA = wx.StaticText(myPanelA, -1, "I have a problem :(") 
     myPanelA.setTextCtrl(self.myTextA) 

     #myPanelB = wx.Panel(self, style=wx.SIMPLE_BORDER) 
     myPanelB = selfUpdatePanel(self, wx.SIMPLE_BORDER, 5, 'Update-panelB', 'Mine too') 
     myPanelB.SetBackgroundColour('#C0FAFF') 
     self.myTextB = wx.StaticText(myPanelB, -1, "Me too :(") 
     myPanelB.setTextCtrl(self.myTextB) 
     mainSizer.Add(myPanelA, 1, wx.EXPAND, 5) 
     mainSizer.Add(myPanelB, 1, wx.EXPAND, 5) 
     self.SetSizer(mainSizer) 

     myPanelB.startThread() 
     myPanelA.startThread() 


if __name__=='__main__': 
    app = wx.App() 
    frame = GUI(parent=None, id=-1, title="Problem Demo") 
    frame.Show() 
    app.MainLoop()