Cannot send posted events for objects in another thread

Question:

When I try to use one QDialog object from threads I get this error.
Here is the code I’m using:

import threading
import test_qdialog
from PyQt4 import QtGui, QtCore


class MyThread(threading.Thread):
    def __init__(self, id, window, mutex):
        self.id = id
        self.window = window
        self.mutex = mutex
        super(MyThread, self).__init__()

    def run(self):
        with self.mutex:
            result = self.window.exec_()
            if result == QtGui.QDialog.Accepted:
                print "Thread %d: %s" % (self.id, self.window.message_input.text())


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)

    mutex = threading.Lock()
    threads = []
    window = test_qdialog.MyDialog()

    for i in range(5):
        thread = MyThread(i, window, mutex)
        thread.start()
        threads.append(thread)

    for thread in threads:
        thread.join()

    sys.exit(app.exec_())

As written in this answer, if I get it right, I can’t do it this way. But how can I do it then?

Asked By: Dmitrii Mikhailov

||

Answers:

You can only create and use GUI widgets on main thread (every UI library that I know is like that). However, you can easily pass signals from threads to main using QtCore.QtThread. See for example the answer to PyQt threads and signals – how to properly retrieve values (even if the answer is not what the OP was looking for, it is relevant to your situation). May also find this SO post useful.

So instead of creating or accessing the dialog from thread, you would emit a signal from thread, and have your main window connected to it create the dialog when it receives the signal. Qt takes care of transfering data between threads. Will work like a charm.

Definitely take a close look at Qt Threading Basics, if you haven’t already (if you have, may want to post questions about parts you don’t understand, there is tons of important info there).

Answered By: Oliver

The QT Widgets can’t be accessed from a thread which is not the main thread. For example, if you call mainwindow.show(), the program will crash.
However, this can be easily addressed using QThread. The principle is that instead of controlling the e.g., mainwindow directly, we can send a signal to the main thread, letting the main thread to call the show() method. A signal can carry anything, such as a String or Integer.
I’d strongly suggest you to watch this video. It will solve your problem in 10 minutes.

Answered By: Mo Zhang
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.