wxpython筆記:wxpython中的多線程實現


GUI的操作必須發生在主線程或應用程序的主循環所處的地方中。

而在wxpython中使用了wxPython的全局函數wx.CallAfter(),該函數是傳遞消息給你的主線程的最容易的方法。

wx.CallAfter()使得主線程在當前的事件處理完成后,可以對一個不同的線程調用一個函數。

傳遞給wx.CallAfter()的函數對象總是在主線程中被執行。

下面是示例程序:

#-*- encoding:UTF-8 -*-
import wx
import threading
import random
class WorkerThread(threading.Thread):
    '''
This just simulates some long-running task that periodically sends
    a message to the GUI thread.
561 / 565
    '''
    def __init__(self,threadNum,window):
        threading.Thread.__init__(self)
        self.threadNum = threadNum
        self.window = window
        self.timeToQuit = threading.Event()
        self.timeToQuit.clear()
        self.messageCount = random.randint(10,20)
        self.messageDelay = 0.1  + 2.0*random.random()

    # 運行一個線程
    def run(self):
        msg = "Thread %d iterating %d times with a delay of %1.4f\n"% (self.threadNum, self.messageCount,self.messageDelay)
        wx.CallAfter(self.window.LogMessage,msg)
        for i in range(1,self.messageCount+1):
            self.timeToQuit.wait(self.messageDelay)
            if self.timeToQuit.isSet():#判斷是否設置了標志位
                break
            msg = "Message %d from thread %d\n" %(i,self.threadNum)
            wx.CallAfter(self.window.LogMessage,msg)
        else:
            wx.CallAfter(self.window.ThreadFinished,self)
    #暫停所有線程
    def stop(self):
        self.timeToQuit.set()
class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,None,title="Multi-threaded GUI")
        self.threads=[]
        self.count=0
        panel=wx.Panel(self)
        startBtn=wx.Button(panel,-1,"Start a thread")
        stopBtn=wx.Button(panel,-1,"Stop all threads")
        self.tc=wx.StaticText(panel,-1,"Worker Threads: 00")
        self.log=wx.TextCtrl(panel,-1,"",style=wx.TE_RICH|wx.TE_MULTILINE)
        inner=wx.BoxSizer(wx.HORIZONTAL)
        inner.Add(startBtn,0,wx.RIGHT,15)
        inner.Add(stopBtn,0,wx.RIGHT,15)
        inner.Add(self.tc,0,wx.ALIGN_CENTER_VERTICAL)
        main=wx.BoxSizer(wx.VERTICAL)
        main.Add(inner,0,wx.ALL,5)
        main.Add(self.log,1,wx.EXPAND|wx.ALL,5)
        panel.SetSizer(main)
        self.Bind(wx.EVT_BUTTON,self.OnStartButton,startBtn)
        self.Bind(wx.EVT_BUTTON,self.OnStopButton,stopBtn)
        self.Bind(wx.EVT_CLOSE,self.OnCloseWindow)

        self.UpdateCount()
    def OnStartButton(self,evt):
        self.count+=1
        thread=WorkerThread(self.count,self)#創建一個線程
        self.threads.append(thread)
        self.UpdateCount()
        thread.start()#啟動線程
    def OnStopButton(self,evt):
        self.StopThreads()
        self.UpdateCount()
    def OnCloseWindow(self,evt):
        self.StopThreads()
        self.Destroy()
    def StopThreads(self):#從池中刪除線程
        while self.threads:
            thread=self.threads[0]
            thread.stop()
            self.threads.remove(thread)
    def UpdateCount(self):
        self.tc.SetLabel("Worker Threads: %d"%len(self.threads))
    def LogMessage(self,msg):#注冊一個消息
        self.log.AppendText(msg)
    def ThreadFinished(self,thread):#刪除線程
        self.threads.remove(thread)
        self.UpdateCount()
app=wx.App()
frm=MyFrame()
frm.Show()
app.MainLoop()

上面這個例子使用了Python的threading模塊。上面的代碼使用wx.CallAfter(func,*args)傳遞方法給主線程。這將發送一個事件給主線程,之后,事件以標准的方式被處理,並觸發對func(*args)的調用。因些,在這種情況中,線程在它的生命周期期間調用LogMessage(),並在線程結束前調用ThreadFinished()。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM