Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 362
Riptyde4 Avatar asked Aug 10 '15 17:08

Riptyde4


1 Answers

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.

like image 67
thorr18 Avatar answered Sep 23 '22 00:09

thorr18