PyQt5: Got AttributeError while using QObject and QThread

762 views Asked by At

I got a problem while I was developing a programme that can retrieve contains from different sites at the same time (now is basically retrieving definition of a word from two or more online dictionaries).

I used QObject and QThread to develop my programme. Everything went fine at first, but when I tried to search for and retrieve contains of another word again, I got 2 AttributeError.

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from gui import Ui_MainWindow
from PyQt5.QtCore import QObject, QThread, pyqtSignal

class Searcher(QObject):
    signalUpdate=pyqtSignal(str, str)

    def __init__(self, dictionary, word):
        super(Searcher, self).__init__()
        self.dictionary=dictionary
        self.word=word
    def run(self):
        self.signalUpdate.emit(self.dictionary, self.word)      

class MyMainWindow(QMainWindow, Ui_MainWindow, QObject):
    signalSearch=pyqtSignal()

    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__()
        self.setupUi(self)
        self.dictList=['Yahoo dictionary', 'Webster dictionary']
        self.searchThreads=[QThread(), QThread()]


    def click(self):
        word=self.lineEdit.text()
        self.searchers=[]

        for dictionary in self.dictList:
            self.searchers.append(Searcher(dictionary, word))

        for index , searcher in enumerate(self.searchers):
            searcher.signalUpdate.connect(self.updateGUI)
            searcher.moveToThread(self.searchThreads[index])
            self.searchThreads[index].start()
            self.signalSearch.connect(searcher.run)

        self.signalSearch.emit()

    def updateGUI(self, dictionary, word):
        print(dictionary+'['+word+']')

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myapp = MyMainWindow()
    myapp.show()

    sys.exit(app.exec_())

I don't know how to deal with this problem. Does anyone know how to get rid of it?

Traceback (most recent call last):
Traceback (most recent call last):
File "C:\workspace\online-dictionary\main.py", line 22, in run
File "C:\workspace\online-dictionary\main.py", line 22, in run
self.signalUpdate.emit(self.dictionary, self.word)      
self.signalUpdate.emit(self.dictionary, self.word)      
AttributeError: 'NoneType' object has no attribute 'signalUpdate'
AttributeError: 'NoneType' object has no attribute 'signalUpdate'
1

There are 1 answers

0
ekhumoro On BEST ANSWER

The problem is caused by deleting the list of searcher objects every time a search is done, which is unnecessary.

You only need to create the searcher objects once, and then make requests to them by emitting signalSearch with the required word.

So the searcher class would look like this:

class Searcher(QObject):
    signalUpdate = pyqtSignal(str, str)

    def __init__(self, dictionary):
        super(Searcher, self).__init__()
        self.dictionary = dictionary

    # word is sent by signalSearch
    def run(self, word):
        self.signalUpdate.emit(self.dictionary, word)

and the main window class would look like this:

class MyMainWindow(QMainWindow, Ui_MainWindow):
    signalSearch = pyqtSignal(str)

    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__()
        self.setupUi(self)
        self.dictList = ['Yahoo dictionary', 'Webster dictionary']
        self.searchThreads = []
        self.searchers = []
        # create all the threads and searchers once
        for dictionary in self.dictList:
            thread = QThread(self)
            self.searchThreads.append(thread)
            searcher = Searcher(dictionary)
            self.searchers.append(searcher)
            searcher.signalUpdate.connect(self.updateGUI)
            self.signalSearch.connect(searcher.run)
            searcher.moveToThread(thread)
            thread.start()

    def click(self):
        # send a new word to the searchers
        self.signalSearch.emit(self.lineEdit.text())

    def updateGUI(self, dictionary, word):
        print(dictionary+'['+word+']')