PyQt - Dialog in another thread
<p>my program has a main window and in this window it runs a thread to read the power from a photodetector then it sends a signal, which is captured by a slot in the main window that updates the main window's gui. </p>

<p>Then I have another widget (let's call it programming widget) that pops from the main window, which is basically a plain text into which the user can insert commands so the program will execute them. Now the issue comes:</p>

<p>When I just open the programming widget with "show", the main window keeps updating the photodetector. However, when I start executing a sequence from the programming widget the main window freezes and the photodetector readings stops with it while is executing the commands (I guess it keeps reading because is in another thread but it stops updating the main window's gui).</p>

<p>My question is: The programming widget is already, by default, in another thread since the main window keeps working when it's popped. So, why it (main window)freezes when the programming widget is in a loop?</p>

<p>Here is the Thread code:</p>

<pre><code>class PDThread(QtCore.QThread):

valueupdate = QtCore.pyqtSignal(float)
state = 1

def __init__(self, state, port):
    QtCore.QThread.__init__(self)
    self.photodetector = PM100D()
    self.port = port

def run(self):
        while True:
            try:
                self.photodetector.connect(self.port)
                break
            except:
                self.dialog = dialog_classes.DialogPort()
                self.dialog.set_instrument('PM100D')
                self.dialog.exec_()
                ret = self.dialog.pm100d.itemText(self.dialog.pm100d.currentIndex())
                if ret == QtGui.QDialog.Accepted:
                    self.port = str(ret)
                else:
                    self.photodetector.__del__()
                    self.quit()
                    return

        window.PDState = 1
        window.startpd.setText('Stop PD')     
        while self.state == 1:
            time.sleep(0.1)
            value = self.photodetector.get_pow()
            self.valueupdate.emit(value)
</code></pre>

<p>Here is the function that creates the thread and the slot in the main window:</p>

<pre><code>def ActionConnect_PM100D(self):
    if self.PDState == 0:
        self.PD = PDThread(self.PDState, self.PDport)
        self.PD.valueupdate.connect(self.PDHandler)
        self.threads = []
        self.threads.append(self.PD)
        self.PD.start()
    else:
        self.PDState = 0
        self.PD.state = 0
        self.startpd.setText('Start PD')


def PDHandler(self, value):
    ref = float(self.refpd.value())
    self.outputpd.setText(str(value-ref))
</code></pre>

<p>Here also in the main window, the function that creates the widget:</p>

<pre><code>    def ActionSetup(self):
    self.program = dialog_classes.Programming(self.newport, self.output, self.outputpd)
    self.program.show()
</code></pre>

<p>Finally, the widget code:</p>

<pre><code>class Programming(QtGui.QDialog, Ui_Programming_Dialog, gui.MyApp):

def __init__(self, ESP300, output, outputpd):
    QtGui.QDialog.__init__(self)
    self.setupUi(self)
    self.setWindowTitle('Programming Setup')
    self.openbuttom.clicked.connect(self.Open)
    self.save.clicked.connect(self.Save)
    self.execute.clicked.connect(self.Execute)
    self.newport = ESP300
    self.output = output
    self.outputpd = outputpd

def Open(self):
    self.fileName = QtGui.QFileDialog.getOpenFileName(self, 'OpenFile', '', '*.txt')
    try:
        text = open(self.fileName).read()
    except:
        None
    else:
        self.program.setPlainText(text)

def Save(self):
    self.fileName = QtGui.QFileDialog.getSaveFileName(self, 'Save File', '', '*.txt')
    try:
        open(self.fileName, 'w').write(str(self.program.toPlainText()))
    except:
        None

def Execute(self):
    text = str(self.program.toPlainText())
    lines = text.split('\n')
    for line in lines:
        arg = []
        List = line.split(',')
        for word in List:
            arg.append(word.strip())

        if arg[0].lower() == 'move':
            if arg[1].lower() == 'x':
                self.newport.move_x(float(arg[2]))
            elif arg[1].lower() == 'y':
                self.newport.move_y(float(arg[2]))
            elif arg[1].lower() == 'z':
                self.newport.move_z(float(arg[2]))
        elif arg[0].lower() == 'wait':
            self.newport.wait()
        elif arg[0].lower() == 'home':
            self.newport.home()
            while True:
                try:
                    self.GetPosition()
                except:
                    time.sleep(0.5)
                else:
                    if self.newport.x == 0 and self.newport.y == 0 and self.newport.z == 0:
                        break
        elif arg[0].lower() == 'power on':
            self.newport.power_on(arg[1])
        elif arg[0].lower() == 'power off':
            self.newport.power_off(arg[1])
        elif arg[0].lower() == 'pos':
            self.newport.pos_x(arg[1])
            self.newport.pos_y(arg[2])
            self.newport.pos_z(arg[3])
            while True:
                try:
                    self.GetPosition()
                except:
                    time.sleep(0.5)
                else:
                    time.sleep(1)
                    break
        elif arg[0].lower() == 'get pos':
            self.GetPosition()
        elif arg[0].lower() == 'get error':
            self.GetError()
        elif arg[0].lower() == 'get pow':
            print(self.outputpd.toPlainText())

        time.sleep(2)


def closeIt(self):
    self.close()
</code></pre>

<p>Thank you for your support.</p>

<p>Generally, the way this is done is to create a class derived from <code>QObject</code> that handles all the non-Qt data collection and move that into a separate thread using the <a href="http://stackoverflow.com/a/38003561/1547004">worker model</a>.</p>

<p>Then, you can use signals to pass data back and forth between the main (GUI) thread and the Worker thread, and to trigger events (like popping up a dialog in the main thread because of an event in the worker thread).</p>

python multithreading qt dialog pyqt