jan
jan

Reputation: 1500

pyqt code is blocking although moved to a different QThread

I tried to make my PyQt4 program more responsive by moving some blocking code to a seperate QThread. As it didn't work, I created this minimal example as a demonstration:

import sys
import time
from PyQt4 import QtCore, QtGui


class Sleeper(QtCore.QObject):

    def __init__(self):
        super(Sleeper, self).__init__()
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.sleep)
        self.timer.start(1000)

    def sleep(self):
        time.sleep(1)


class MyGUI(QtGui.QMainWindow):

    def __init__(self, parent=None):
        super(MyGUI, self).__init__(parent)
        self.button = QtGui.QPushButton("hello", self)
        self.sleeper = Sleeper()
        self.thread = QtCore.QThread()
        self.sleeper.moveToThread(self.thread)
        self.thread.start()


if __name__ == "__main__":
    qapp = QtGui.QApplication(sys.argv)
    my_gui = MyGUI()
    my_gui.show()
    qapp.exec_()

The problem with this code is that the sleep-command still blocks the user interface. I found that it works as expected when I create, connect and run the QTimer outside the Sleeper class, but I do not understand why.

Upvotes: 2

Views: 1206

Answers (1)

Gábor Imre
Gábor Imre

Reputation: 6299

The connect is called while the object was in the GUI thread so the event handler will also be executed in the GUI thread. Try moving to thread first, then creating the connection.

class Sleeper(QtCore.QObject):

    def __init__(self):
        super(Sleeper, self).__init__()
        self.timer = QtCore.QTimer()

    def initialize(self): # Creating the connection and starting separately
        self.timer.timeout.connect(self.sleep)
        self.timer.start(1000)

    def sleep(self):
        time.sleep(1)

class MyGUI(QtGui.QMainWindow):

    def __init__(self, parent=None):
        super(MyGUI, self).__init__(parent)
        self.button = QtGui.QPushButton("hello", self)
        self.sleeper = Sleeper()
        self.thread = QtCore.QThread()
        self.sleeper.moveToThread(self.thread) # Move to thread
        self.sleeper.initialize() # Create connection now
        self.thread.start()

Also, check this: Qt connection type between threads: why does this work?

Upvotes: 6

Related Questions