在wxPython中使用多线程

来源:互联网 发布:linux halt命令 编辑:程序博客网 时间:2024/06/06 00:27
wxPython是GUI库,一般GUI库都是只能在主线程中渲染。而渲染引擎现在只有两个一个是微软的Directx,一个就是开源Api的OpenGL。OpenGL是不支持多线程的,Directx我就不知道了,基本上没有接触过.
Python本身有一个threading的多线程库,非常好用。
同时还有一个线程安全的列队库Queue。使用Quete列队,就可以在多个线程之间传递消息了。
如果要使用wxPython作比较复杂的GUI应用程序,你可以使用上边的Queue来处理线程间的消息,可以给主线程定义两个列队,一个用来接收来自其他子线程的消息,一个用来给其他子线程发送数据.同时还可以使用我上一遍文章中的threading.Event()在主线程或者其他线程中启动另一个线程.这样作之后,我们就可以把和GUI无关的所有工作都放在别的线程处理,只在主线程进行GUI相关的显示数据绘制.
wxPython有一个子线程调用主线程UI控件的方法wx.CallAfter(),子线程调用这个方法之后,主线程的UI可以在当前事件处理结束后处理子线程发送的消息,这是wxPython中子线程给主线程发送消息最简单的方法了。
看的一个关于wxPython教程中给出了一个例子:

#!/usr/bin/env python

# -*- coding: 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.

    '''

    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 stop(self): 

        self.timeToQuit.set()

    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)

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

frm = MyFrame() 

frm.Show() 

app.MainLoop()


下边是运行结果截图:

在wxPython中使用多线程 - ♂苹果 - 眼睛想旅行

 

原创粉丝点击