【问题标题】:Trying to create a dialog in another thread wxpython试图在另一个线程 wxpython 中创建一个对话框
【发布时间】:2015-11-02 16:53:33
【问题描述】:

我正在另一个线程中运行一个函数,该函数应该填写一个对话框然后显示它,但只要我试图以任何方式更改对话框,它就会出现段错误。我读到这是 WxPython 的一个常见问题,并且开发人员不打算直接更改另一个线程中的对话框。

我该如何解决这个问题?我可以在我的主线程中调用该函数,但这会阻塞我的 GUI,并且初始化对话框是一个冗长的操作 - 我想避免这种情况。

我的代码与下面类似。

在主线程中

# Create the dialog and initialize it
thread.start_new_thread(self.init_dialog, (arg, arg, arg...))

我正在调用的函数

def init_dialog(self, arg, arg, arg....):
  dialog = MyFrame(self, "Dialog")

  # Setup the dialog
  # ....
  dialog.Show()

即使有一个空白对话框并且只是一个简单的调用来显示函数内部,我也会遇到分段错误。任何帮助将不胜感激,谢谢。

【问题讨论】:

  • 在工作线程上尝试使用 GUI 组件并不是一个好主意。当以这种方式使用 GUI 组件时,我认为包括 wxPython 在内的大多数 GUI 框架都无法正常工作。确实这里有一篇关于在工作线程中使用 wxPython 的文章wiki.wxpython.org/Non-Blocking%20Gui
  • 使用容器类(class foo : pass),添加、删除、更新、调用函数合并你的应用。
  • 为什么不在单独的线程中运行“长度操作”,而是在主线程中运行对话框?
  • @tom10 因为主线程将不得不等待操作完成,这是我不想要的。该操作生成一个图形,该图形必须显示在对话框中
  • 通常的处理方法是在主线程中点击一个按钮,在不同的线程中进行计算(这样主线程和 GUI 仍然响应),显示一个指示器(如主线程中的“throbber”)表示正在执行计算,然后在计算完成时在主线程中弹出对话框。也就是说,如果您必须等待,那么您就等待,但您不想阻塞主线程或让用户对正在发生的事情一无所知。

标签: python multithreading dialog wxpython wxwidgets


【解决方案1】:

我制作了一个小程序来演示在计算期间保持 GUI 响应并在计算后调用消息框。

    import wx
    import threading
    import time


    class TestFrame(wx.Frame):

        def __init__(self):
            wx.Frame.__init__(self, None, -1, "I am a test frame")
            self.clickbtn = wx.Button(self, label="click me!")
            self.Bind(wx.EVT_BUTTON, self.onClick)

        def onClick(self, event):
            self.clickbtn.Destroy()
            self.status = wx.TextCtrl(self)
            self.status.SetLabel("0")
            print "GUI will be responsive during simulated calculations..."
            thread = threading.Thread(target=self.runCalculation)
            thread.start()

        def runCalculation(self):
            print "you can type in the GUI box during calculations"
            for s in "1", "2", "3", "...":
                time.sleep(1)
                wx.CallAfter(self.status.AppendText, s)
            wx.CallAfter(self.allDone)

        def allDone(self):
            self.status.SetLabel("all done")
            dlg = wx.MessageDialog(self,
                                   "This message shown only after calculation!",
                                   "",
                                   wx.OK)
            result = dlg.ShowModal()
            dlg.Destroy()
            if result == wx.ID_OK:
                self.Destroy()

    mySandbox = wx.App()
    myFrame = TestFrame()
    myFrame.Show()
    mySandbox.MainLoop()

GUI 内容保存在主线程中,而计算继续不受阻碍。计算结果可根据您的需要在创建对话框时使用。

【讨论】:

  • 在调用 dlg.ShowModal() 之后我们总是需要调用 dlg.Destroy() 吗?
  • @masphei 是的。但是,这一切都适用于已淘汰的旧 wx“经典”内容。我认为 wx "Phoenix" 的工作方式不同,不幸的是他没有将其称为 "wx2",因此您所查看的示例并不总是很明显。
猜你喜欢
  • 1970-01-01
  • 2017-01-27
  • 2017-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多