在wxpython中,像其它GUI框架一样,如果要进行耗时很长的任务,需要将该任务放在工作线程中运行,以保证程序的响应性。工作线程可能会需要与主线程进行交互。这可以分为两种情况:一是工作线程只是向主线程单向通知工作进行的状态,比如任务完成进度,并不要求主线程回应。第二种情况是工作线程要调用主线程的方法,并且要求其返回,例如工作线程运行中需要弹出对话框让用户输入必要的信息(在wxpython中,显示对话框必须在主线程中进行)。
对于第一种情况,wxwiki已经谈了很多了,一种是工作进行使用wx.CallAfter主要调用主线程的方法,一种是工作线程发布事件(也是利用CallAfter),主线程监听该事件。第一种方法用起来要简单一些,但不如第二种方法灵活。对于第二种情况,wxwiki却很少谈到,网上也很少谈到其解决方法。不能使用CallAfter的原因在于CallAfter是异步调用,它只是将调用放在事件队列中,调用就返回了。如果我们想要等待调用在主线程中执行完毕再返回,就得使用别的方法。在Swing中存在InvokeAndWait就是为了达到此目的,在wxpython却不存在这样的方法,所幸很容易使用python的线程类Event达到类似的效果。
import wx
import threading
def call_and_wait(target, *args, **kwargs):
if wx.Thread_IsMain():
return target(*args, **kwargs)
else:
context = {}
context['event'] = threading.Event()
wx.CallAfter(call_in_mainthread, context, target, *args, **kwargs)
context['event'].wait()
return context['result']
def call_in_mainthread(context, target, *args, **kwargs):
context['result'] = target(*args, **kwargs)
context['event'].set()
主要思想是在工作线程创建一个Event对象,然后利用CallAfter放在主线程中去调用,工作线程调用event.wait()开始等待,当主线程执行完调用之后,设置event的状态,这样工作线程开始继续运行。下面是使用这个方法的一个例子:
class WorkThread(Thread):
def run():
# ...
call_and_wait(ShowSomeDialog)
def ShowSomeDialog():
# display some dialog
dlg = UserPassDialg(None)
if dlg.ShowModel() == wx.ID_OK:
return (dlg.Username, dlg.Password)
else:
return None
call_and_wait调用很别扭,利用decorator我们可以取消该方法的调用,取而代之我们把它的调用放到decorator去做。
def mainthread(func, *args, **kwargs):
'''ensure func invoked in main thread'''
def _func():
return call_and_wait(func, *args, **kwargs)
return _func
这样我们可以将前面的例子改写成:
class WorkThread(Thread):
def run():
# ...
ShowSomeDialog()
@mainthread
def ShowSomeDialog():
# display some dialog
dlg = UserPassDialg(None)
if dlg.ShowModel() == wx.ID_OK:
return (dlg.Username, dlg.Password)
else:
return None
似乎上面的代码并没有简洁多少,但是如果碰到需要大量调用主线程的方法时候,使用decorator可以避免创建许多一次性的方法。例如,在应用使用sqlite的情况下,由于sqlite只能单线程使用,所以也不能在工作线程中调用sqlite方法,通常的方法就是将所有sqlite调用都放到主线程中去做。
@mainthread
def get_account(id):
#....
@mainthread
def save_account(account):
#...
# more sqlite methods
分享到:
相关推荐
wxpython中文教程wxpython中文教程wxpython中文教程wxpython中文教程wxpython中文教程wxpython中文教程wxpython中文教程wxpython中文教程wxpython中文教程
Python GUI制作实例 wxPython使用多线程 防假死含wxFormBuilder的文件及源码
1、实现的跨平台Python+wxPython界面,程序中添加了OpenCV代码进行简单的图像处理(截图),适合新手借鉴,利用wxPython库进行Python界面制作,如何在Python中调用OpenCV进行图像处理。 2、代码可以在Linux和Windows...
最新wxpython中文文档,根据官方文档排版,变量,api等为英文,相关解释为中文,更好编辑
网上关于python多线程防假死与线程传递消息是几年前的,这里由于wxpython和threading模块已经更新最新,因此给出最新修改代码,能在2017年最新版的python和模块中运行。 原来的publisher()和callafter都无法使用。 ...
一个WxPython界面利用pubsub 展示进程工作的进度条的例子,实际使用, 只要修改 WorkThread 里的 run 内容 及 MainFrame 里的 updateDisplay 内容即可。
wxPython中文教程 简单入门加实例 教程里说得很详细,对于刚开始学习WXPython的人很有帮助
使用python做UI也是必将对的,这是收集了wxPython中文资料,供学习交流使用
wxPython中,有三个“线程安全”的函数。如果你在更新UI界面时,三个函数都不使用,那么你可能会遇到奇怪的问题。有时GUI也忙运行挺正常,有时却会无缘无故的崩溃。因此就需要这三个线程安全的函数:wx.PostEvent, ...
wxpython 界面编程 中文 word 文档
几本很不错的关于python gui的wxPython的书,包括“wxPython in Action(中文版)” 活学活用wxPython “《wxPython in Action》Noel Rappin, Robin Dunn著 2006年版”
学习wxPython的中文word文档,供大家参考
wxPython中文教程,翻译自wxPython in Action。其中增加了目录,及阅读笔记,并对部门做了纠错处理。 另外增加了官方文档部分翻译内容。是初学者的最佳选择。
前段时间我编写了一个工业控制的软件,在使用中一直存在一个问题,就是当软件检索设备时,因为这个功能执行的时间比较长,导致GUI界面假死,让用户分辨不清楚软件到底仍在执行,还是真的挂掉了。(虽然我设计了同步...
中文翻译的不是很好,但是可以作为一开始的读物,毕竟中文的读起来更顺手些,很多东西都是看了英文才明白,英文讲的清楚些,把这两本书打了个包,分享给大家!
wxpython 教程 很不错的资料 有关于多线程的教程
wxpython 中 wxGrid 控件的补充材料
wxPython and PyOpengl源码 演示如何在wxPython构建的GUI中使用pyopengl绘制场景