Proper use of Qthread subclassing works, better method?

2.4k views Asked by At

I have developed a multithreaded gui that reads serial data in a separate thread. I am very new to threading, pyqt, python in general. I used this site as a reference to get this far and its working properly but researching how to add a second thread I discovered a number of articles and posts that you shouldn't subclass threads. How would I go about converting this to the "proper" method?

class AThread(QtCore.QThread):
    updated = QtCore.pyqtSignal(str)
    query = QtCore.pyqtSignal(str)

    def __init__(self):
        QtCore.QThread.__init__(self)

    def run(self):
        try:
            while True:
                if ser.in_waiting:
                    line=ser.readline()[:-2]#remove end of line \r\n
                    self.updated.emit(line.decode('utf-8'))
                    if main_window.keywordCheckBox.isChecked():
                        if main_window.keywordInput.text() in line.decode('utf-8'):
                            self.query.emit("Match!")
                            self.query.emit(line.decode('utf-8'))
        except serial.serialutil.SerialException:
            pass

class MyMainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        self.thread= AThread()
        self.thread.updated.connect(self.updateText) 
        self.thread.query.connect(self.matchFound)
1

There are 1 answers

1
finmor On BEST ANSWER

Here is an article from the Qt documentation that you may find helpful http://doc.qt.io/qt-4.8/thread-basics.html

There is a paragraph named "Which Qt Thread Technology Should You Use?" conataining a table which suggests what approach to use depending on what you want to achieve

Possibly in your case you might need to follow one of the approaches described in the last two rows of the table.

If this is the case then your code should look like this

class AWorker(QObject):
    #define your signals here
    def __init__(self):
       super(AWorker, self).__init__()

    def myfunction(self):
        #Your code from run function goes here.
        #Possibly instead of using True in your while loop you might 
        #better use a flag e.g while self.running:
        #so that when you want to exit the application you can
        #set the flag explicitly to false, and let the thread terminate 

class MainWindow(...)
    def __init__(...)
        ...
        self.worker = AWorker()
        self.thread = QThread()
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.myfunction)
        #Now you can connect the signals of AWorker class to any slots here
        #Also you might want to connect the finished signal of the thread
        # to some slot in order to perform something when the thread
        #finishes
        #e.g,
        self.thread.finished.connect(self.mythreadhasfinished)
        #Finally you need to start the thread
        self.thread.start()