我有一个来自threading.Thread的子类,我用来创建wx.Panels(因为它们大多数是I / O绑定的),并通过wx.PostEvent将它们发送到我的wx.Frame。

问题是线程结束后,发送的面板被破坏并丢失,使框架空白。我认为这与以下事实有关:线程本身在执行后就被破坏了。在线程的最后一行中添加time.sleep(s)可以在几秒钟内看到框架内的面板,而线程被冻结,证明该面板实际上是创建的。

这是可能会让您感兴趣的框架的代码:

self.Bind(MyEvents.EVT_CONTROL_NEWPANEL,self.ChangePanel)
def ChangePanel(self,event):
    if self.panel != None:
        self.panel.Hide()
    self.panel = event.panel
    self.panel.Show()


和一个threading.thread子类:

class ThreadExecute(threading.Thread):
    def __init__(self,func,args):
        threading.Thread.__init__(self)
        self.func = func
        self.args = args
        self.start()

    def run(self):
        apply(self.func,self.args)

CreateRandomPanel(parent):
    panel = RandomPanel(parent)
    event = MyEvents.Control_NewPanel(panel = panel)
    wx.PostEvent(parent,event)


线程结束后是否有办法使对象保持活动状态?
在线程上腌制对象并在框架上去腌制是一个很好的选择吗?

编辑:

一个小的可运行代码示例:

import wx
import threading
from wx.lib.newevent import NewEvent
from time import sleep

NewPanelEvent, EVT_NEWPANEL = NewEvent()
class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,None,size=wx.Size(350,350))
        self.panel = None
        self.Bind(EVT_NEWPANEL,self.ChangePanel)
        self.control = MyControl(self)
        self.control.NewPanel()

    def ChangePanel(self,event):

        if self.panel != None:
            self.panel.Hide()

        self.panel = event.panel
        #self.Refresh()

class MyPanel(wx.Panel):
    def __init__(self,parent,size):
        wx.Panel.__init__(self,parent,size=size)
        self.btn = wx.Button(self,label='hit me!',pos=wx.Point(25,25),size=wx.Size(75,25))
        self.SetBackgroundColour(wx.Colour(255,255,0))

class MyControl(object):
    def __init__(self,window):
        self.window = window

    def NewPanel(self):
        MyThread(RandomFunction,(self.window,))

class MyThread(threading.Thread):
    def __init__(self,func,args):
        threading.Thread.__init__(self)
        self.func = func
        self.args = args
        self.start()

    def run(self):
        apply(self.func,self.args)

def RandomFunction(window):
    sleep(3)
#    size = window.GetSizeTuple()
    size = (250,250)
    panel = MyPanel(window,size=size)
    event = NewPanelEvent(panel = panel)
    wx.PostEvent(window,event)
    # use the sleep to prevent the thread from ending, so you can see the panel
    sleep(5)

class App(wx.App):
    def OnInit(self):
        self.frame = MyFrame()
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True

def main():
    app = App(False)
    app.MainLoop()

if __name__ == '__main__':
    main()

最佳答案

我看不到您实际在何处传递RandomPanel的位置。创建它,然后在函数结束时将其销毁。您实际上不会通过面板,而只会通过父面板。就个人而言,我将使用wx.CallAfter将PubSub消息发送到您的主应用程序类,并在其中创建面板,或者只是在PubSub消息中传递面板。

这是关于Pubsub的教程:


http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/


这是一个带有pubsub和线程的代码:


http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/

关于python - 从threading.Thread子类返回wx.Panel,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12385833/

10-15 23:42