wxPython线程,该线程不阻止GUI



我是wxPython和线程的新手。我正在尝试将一些代码移动到线程中,这样它在执行时就不再阻塞我的GUI,并且我可以按下另一个按钮来终止线程。然而,完成了这项工作后,代码仍然会阻塞我的GUI。如何编写这些代码,使线程不会阻塞GUI?

import wx, sys
import threading
import time

class mywxframe(wx.Frame):
    global sizer2, WorkerThread
    def __init__(self):
        wx.Frame.__init__(self, None)
        pnl = wx.Panel(self)
        szr = wx.BoxSizer(wx.VERTICAL)
        pnl.SetSizer(szr)
        szr2 = sizer2(self, pnl)
        szr.Add(szr2, 1, wx.ALL | wx.EXPAND, 10)
        log = wx.TextCtrl(pnl, -1,style=wx.TE_MULTILINE, size=(300,-1))
        szr.Add(log, 1, wx.ALL, 10)
        btn3 = wx.Button(pnl, -1, "Stop")
        btn3.Bind(wx.EVT_BUTTON, self.OnStop)
        szr.Add(btn3, 0, wx.ALL, 10)
        redir = RedirectText(log)
        sys.stdout=redir
        szr.Fit(self)
        self.Show()

    def sizer2(self, panel):
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        btn2 = wx.Button(panel, -1, "OK",)
        self.Bind(wx.EVT_BUTTON, self.OnStart, btn2)
        sizer.Add(btn2, 0, wx.ALL, 10)
        return sizer

    def WorkerThread(self):    
        self.dead = False
        while (not self.dead):
            for i in range(0,10):
                print "printing", i
                time.sleep(3)
    def OnStart(self, event):
         our_thread = threading.Thread(target=WorkerThread(self))
         our_thread.start()
    def OnStop(self, event):
        self.dead = True

class RedirectText(object):
    def __init__(self, aWxTextCtrl):
        self.out=aWxTextCtrl
    def write(self, string):
        self.out.WriteText(string)


app = wx.PySimpleApp()
frm = mywxframe()
app.MainLoop()

您有几个问题。

首先,如果要将sizer2WorkerThread定义为方法,则应该将它们用作方法,而不是全局方法。

接下来,在创建线程时,调用WorkerThread并将其返回值(None)传递给线程。这就是您阻止GUI的地方。

    def OnStart(self, event):
        our_thread = threading.Thread(target=WorkerThread(self))
        our_thread.start()

相反,您应该将一个可调用对象(不带()WorkerThread)传递给线程,以便它能够在新线程的上下文中调用它。

最后,由于self.out.WriteText操作UI对象,因此必须在GUI线程的上下文中调用它。使用wx.CallAfter是一种简单的方法。

以下是您的示例更新了这些更改:

import wx, sys
import threading
import time
print wx.version()
class mywxframe(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)
        pnl = wx.Panel(self)
        szr = wx.BoxSizer(wx.VERTICAL)
        pnl.SetSizer(szr)
        szr2 = self.sizer2(pnl)
        szr.Add(szr2, 1, wx.ALL | wx.EXPAND, 10)
        log = wx.TextCtrl(pnl, -1,style=wx.TE_MULTILINE, size=(300,-1))
        szr.Add(log, 1, wx.ALL, 10)
        btn3 = wx.Button(pnl, -1, "Stop")
        btn3.Bind(wx.EVT_BUTTON, self.OnStop)
        szr.Add(btn3, 0, wx.ALL, 10)
        redir = RedirectText(log)
        sys.stdout=redir
        szr.Fit(self)
        self.Show()

    def sizer2(self, panel):
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        btn2 = wx.Button(panel, -1, "OK",)
        self.Bind(wx.EVT_BUTTON, self.OnStart, btn2)
        sizer.Add(btn2, 0, wx.ALL, 10)
        return sizer

    def WorkerThread(self):    
        self.dead = False
        while (not self.dead):
            for i in range(0,10):
                print "printing", i
                if self.dead:
                    break
                time.sleep(3)
        print 'thread exiting'
    def OnStart(self, event):
        our_thread = threading.Thread(target=self.WorkerThread)
        our_thread.start()
    def OnStop(self, event):
        self.dead = True

class RedirectText(object):
    def __init__(self, aWxTextCtrl):
        self.out=aWxTextCtrl
    def write(self, string):
        wx.CallAfter(self.out.WriteText, string)

app = wx.App()
frm = mywxframe()
app.MainLoop()

相关内容

  • 没有找到相关文章