【发布时间】:2018-10-13 03:37:17
【问题描述】:
即使解释器和wx.App 都必须在主线程上运行,如何通过cmd2 解释器命令创建非阻塞wxPython GUI 窗口?
我正在使用 cmd2 模块在 Python 3.x 中创建命令行解释器。我的解释器中的一个命令将允许我创建一个“非阻塞”wxPython GUI 窗口,该窗口带有一个在单独线程中运行的倒数计时器。它需要与主解释器线程分开运行,否则它将阻止在计时器运行时输入其他命令。
当我尝试使用 wxTimer 对象来允许我的 GUI 更新其进度条并检查剩余时间时,我收到以下错误:
wx._core.wxAssertionError: C++ assertion "wxThread::IsMain()" failed at ..\..\src\common\timerimpl.cpp(60) in wxTimerImpl::Start(): timer can only be started from the main thread
任何启动计时器的尝试都会破坏代码。例如,下面的简单代码不起作用:
import wx
import threading
import cmd2
class TimerFrame(wx.Frame):
def __init__(self, time):
super().__init__(None, title=str(time), size=(300, 300))
self.InitUI()
def InitUI(self):
self.timer = wx.Timer(self, 1)
self.timer.Start(100)
self.Bind(wx.EVT_TIMER, self.OnTimer, id=1)
self.Show()
def OnTimer(self, event):
print("Updating")
class Interpreter(cmd2.Cmd):
def __init__(self):
super().__init__()
self.app = wx.App()
def do_timer(self, _):
threading.Thread(target=self.createTimer, args=(self.app,)).start()
def createTimer(self, app):
TimerFrame("Window Title")
app.MainLoop()
if __name__ == "__main__":
Interpreter().cmdloop()
请注意,注释掉包含timer.Start(100) 的行允许在单独的线程中成功创建窗口,但它们缺少必要的Timer 功能。
我尝试过的其他不起作用的方法:
- 在新线程中创建
wx.App而不是传递它(导致相同的错误,但针对MainLoop而不是Timer) - 在主线程中创建
wx.App并在那里运行它的MainLoop(阻止命令行接受更多命令) - 在单独的线程中运行解释器命令循环(抱怨
cmdloop必须从主线程运行)
【问题讨论】:
-
至于为什么会死掉,timer使用timer信号,python将信号限制在主线程。
标签: python multithreading python-3.x wxpython wxwidgets