Riptyde4
Riptyde4

Reputation: 5460

Trying to create a dialog in another thread wxpython

I'm running a function in another thread that is supposed to fill out a dialog and then show it but it just seg faults as soon as I tried to alter the dialog in any way. I've read that this is a common issue with WxPython and that devs are not intended to directly alter dialogs in another thread.

How do I get around this? I can just call the function in my main thread but that will block my GUI and it is a lengthy operation to initialize the dialog - I would like to avoid this.

My code is similar to the below.

In the main thread

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

The function I am calling

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

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

Even with a blank dialog and just a simple call to show inside the function I get a segmentation fault. Any help would be greatly appreciated, thanks.

Upvotes: 5

Views: 2676

Answers (1)

thorr18
thorr18

Reputation: 347

I have made an applet to demonstrate keeping GUI responsive during calculations and calling the message box after the calculations.

    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 stuff is kept in the main thread, while calculations continue unhindered. The results of the calculation are available at time of dialog creation, as you required.

Upvotes: 5

Related Questions