我的代码(Ubuntu 18.04,Python 2.7,wxPython 4)创建带有状态栏的用户界面,然后启动子进程。新过程尝试更新状态栏文本,但更改不会显示在状态栏中。
示例代码显示了我要完成的工作:
import wx, multiprocessing
class MyFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(300,200))
self.sb = self.CreateStatusBar()
self.sb.SetStatusText('Original text')
self.Show(True)
def doWork():
print 'In doWork'
print frame.sb.GetStatusText()
frame.sb.SetStatusText('New stuff')
print frame.sb.GetStatusText()
p = multiprocessing.Process(target=doWork, args=())
app = wx.App(False)
frame = MyFrame(None, 'Status Text')
p.start()
app.MainLoop()
doWork
进程可以访问和打印原始状态栏文本,并且似乎能够设置状态文本(基于第二次打印的结果)。但是状态栏中显示的文本不会改变。有没有办法可以通过单独的过程更新状态栏文本?
答案 0 :(得分:1)
Gui程序在其主循环中运行,我相信,更新必须在主循环内进行。 (有人可能在这里或确实澄清,告诉我我错了)。
通常,实现此目标的方法是从wx.lib.newevent
生成事件或使用类似pubsub
的事件。但是,这些通常是由Thread
而非Process
生成的,同样,有人可以纠正我(我和下一个男人一样模糊)。
查看此处:Python multiprocessing, PyAudio, and wxPython
此处:wxpython 3.0 & multiprocessing - update GUI from background process
以获得背景信息
这里是详细的解决方法:https://wiki.wxpython.org/MultiProcessing
答案似乎是使用Queue
中的multiprocessing
并使用wx.Timer
来定期检查该队列是否有更新。
我整理了一个快速脚本来说明您的代码的解决方案。至少,这应该是一个可以开始的合理起点。
除了最初更改状态文本外,它还会每5秒更新一次,以证明这一点。
import multiprocessing
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(300,200))
self.sb = self.CreateStatusBar()
self.sb.SetStatusText('Original text')
self.Show(True)
self.timer = wx.Timer(self)
self.process_timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.poll, self.timer)
self.Bind(wx.EVT_TIMER, self.process, self.process_timer)
self.timer.Start(1000)
self.process_timer.Start(5000)
self.cnt = 0
# Poll for a queue entry with which to update the statusbar
def poll(self, event):
print("Polling")
if q.empty():
return
q_mess = q.get()
self.sb.SetStatusText(q_mess)
#Fire off a new process every 5 seconds to demonstrate the update
def process(self, event):
self.cnt += 1
p = multiprocessing.Process(target=doWork, args=(q,self.cnt))
p.start()
def doWork(q,cnt=0):
print ('In doWork')
q.put("New status "+str(cnt))
q = multiprocessing.Queue()
p = multiprocessing.Process(target=doWork, args=(q,0))
app = wx.App(False)
frame = MyFrame(None, 'Status Text')
p.start()
app.MainLoop()