在主线程中获取子线程创建的对象

1 投票
2 回答
687 浏览
提问于 2025-04-16 03:19

假设我想一次性创建500个wxWidget,比如一些面板、颜色按钮和文本框等等。如果我把这些都放在主线程里创建,主线程就会卡住,所以我把创建的部分放到子线程里,同时在主线程里显示一些GIF动画。但是,我发现我无法在子线程中创建的wxWidget对象在主线程中使用。

我能不能把在子线程中创建的wxWidgets拿到主线程里? 简单来说,假设我需要在子线程中创建一个框架的子组件,而主线程则显示动画。一旦子线程完成所有子组件的创建,这些子组件应该能在主线程中使用。

任何帮助都非常感谢。

我在使用的是Python 2.5和wxPython 2.8,操作系统是Windows XP。

2 个回答

0

你可以通过一个队列把它们发送回去,或者所有这些操作都在一个类的实例中进行,把这些小部件放在这个实例的某个固定位置,方便主线程来获取它们。可以通过信号量来进行通知。

2

你可以使用 pubsub,这个工具已经包含在wxpython里,路径是 wx.lib.pubsub

你可以查看 我在这里的回答,里面有一个关于线程间通信的基本使用示例。


另外一个选择是:一个示例,展示如何使用 wx.Yield 来保持你的窗口更新。

import wx

class GUI(wx.Frame):
    def __init__(self, parent, title=""):
        wx.Frame.__init__(self, parent=parent, title=title, size=(340,380))
        self.SetMinSize((140,180))

        self.creating_widgets = False

        self.panel = wx.Panel(id=wx.ID_ANY, parent=self)

        self.startButton = wx.Button(self.panel, wx.ID_ANY, 'Start')
        self.stopButton = wx.Button(self.panel, wx.ID_ANY, 'Stop')
        self.messageBox = wx.TextCtrl(self.panel, wx.ID_ANY, '', size=(75, 20))

        self.Bind(wx.EVT_BUTTON,  self.onStart, self.startButton)     
        self.Bind(wx.EVT_BUTTON,  self.onStop, self.stopButton)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.startButton, 0, wx.ALL, 10)
        self.sizer.Add(self.stopButton, 0, wx.ALL, 10)
        self.sizer.Add(self.messageBox, 0, wx.ALL, 10)

        self.panel.SetSizerAndFit(self.sizer)

    def onStart(self, event):
        self.creating_widgets = True
        count = 0
        self.startButton.Disable()
        while self.creating_widgets:
            count += 1
            #Create your widgets here

            #just for simulations sake...
            wx.MilliSleep(100)
            self.messageBox.SetLabel(str(count))

            #Allow the window to update, 
            #You must call wx.yield() frequently to update your window
            wx.Yield()

    def onStop(self, message):
        self.startButton.Enable()
        self.creating_widgets = False


if __name__ == "__main__":

    app = wx.PySimpleApp()
    frame = GUI(None)
    frame.Show()
    app.MainLoop()

撰写回答