【问题标题】:Updating GUI while execution a python function while keeping this function GUI-independent在执行 python 函数时更新 GUI,同时保持此函数与 GUI 无关
【发布时间】:2012-11-16 13:26:22
【问题描述】:
我有一个 python 函数,它接受一些参数并执行一些任务(我们称之为 theFunc)。当 theFunc 运行时,内部变量 resultsMessage 的行数越来越多,我在执行结束时在 GUI 上显示它。理想情况下,我希望在执行 theFunc 时在 GUI 上显示和更新结果消息,而不是在它完成之后,并且在不污染 theFunc 的情况下执行它(它已经足够复杂了)。最好的方法是什么?
我能想到的两种可能的方法(两者都很牵强):
- 有两个线程:一个执行 theFunc 并将结果消息写入变量/文件,另一个检查此变量/文件并更新 GUI;
- 不将行附加到结果消息,而是将一些“流”附加到 GUI 元素;向“流”添加行将更新 GUI。
我想应该有一种传统的方式来做到这一点。
环境:CPython 2.7、Win XP、WXPython
【问题讨论】:
标签:
python
user-interface
wxpython
auto-update
【解决方案1】:
您会想要使用线程。 wxPython 提供了几个线程安全的方法,例如 wx.CallAfter、wx.CallLater 和 wx.PostEvent。您也可以将它们与 pubsub 结合起来发送消息!在您的情况下,我认为将 wx 方法与您希望显示的任何文本一起传递给 wx.CallAfter 都可以。
【解决方案2】:
Mike Driscoll 的回答描述了可能是最常用的方法。他在他的网站上有一篇非常好的文章,其中更详细,here。他那里其实有很多非常好的文章,去看看吧。
另一种方法是在主线程中设置一个计时器,用于检查队列中的消息。您在 init 方法中设置队列并将其传递给运行长时间运行函数的工作线程。工作人员根据需要将内容放入队列中,与计时器事件相关的函数在主线程中提取消息/数据并更新 GUI 等。这是一个简短的示例:
#first 4 lines are the bottom of the __init__ method of the main frame
self.timer = wx.Timer(self)
self.timer.Start(250)
self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)
self.Bind(wx.EVT_CLOSE, self.onClose)
def onTimer(self, event):
'''checks for messages in self.q2 (Queue.Queue set up above)'''
while not self.q2.empty():
msg, data = self.q2.get()
self.update(None, msg, data)
def update(self, event, msg, data):
'''Runs with data returned in self.q2'''
self.sb.SetStatusText(msg)
etc, etc . . .
祝你好运,迈克