wxPython-从子进程更改状态栏文本

时间:2019-05-12 23:20:12

标签: wxpython

我的代码(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进程可以访问和打印原始状态栏文本,并且似乎能够设置状态文本(基于第二次打印的结果)。但是状态栏中显示的文本不会改变。有没有办法可以通过单独的过程更新状态栏文本?

1 个答案:

答案 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()

enter image description here