Python 使用PyQt5轻松实现多线程,用于更新QTextBrowser内容

Python 使用PyQt5轻松实现多线程,用于更新QTextBrowser内容,python,python-3.x,pyqt,pyqt5,Python,Python 3.x,Pyqt,Pyqt5,我在网上发现一些东西表明PyQt5小部件不是线程安全的。 其他Stackoverflow的答案建议创建一个只适合他们问题的类。我尝试在Python3中使用\u-thread模块,该模块适用于除PyQt之外的所有功能 app = QApplication([]) Ui_MainWindow, QtBaseClass = uic.loadUiType("UI/action_tab.ui") #specify the location of your .ui file class MyApp(QM

我在网上发现一些东西表明PyQt5小部件不是线程安全的。 其他Stackoverflow的答案建议创建一个只适合他们问题的类。我尝试在Python3中使用
\u-thread
模块,该模块适用于除PyQt之外的所有功能

app = QApplication([])
Ui_MainWindow, QtBaseClass = uic.loadUiType("UI/action_tab.ui") #specify the location of your .ui file


class MyApp(QMainWindow):
    def __init__(self):
        super(MyApp, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.threadPool = QThreadPool()
        self.ui.queryBox.returnPressed.connect(self.load_response)

    def start_loader(self):
        self.loading_animate = QMovie('IMAGES/GIFS/load_resp.gif')
        self.loading_animate.setScaledSize(QSize(400, 300))
        self.ui.loader.setMovie(self.loading_animate)
        self.loading_animate.setSpeed(200)
        self.ui.loader.show()
        self.loading_animate.start()

    def stop_loader(self):
        self.ui.loader.hide()
        self.loading_animate.stop()

    def get_response(self):
        plain_text, speech = get_Wresponse(self.ui.queryBox.displayText())
        self.stop_loader()
        self.ui.textDisplay.setText(plain_text)
        if speech == '':
            say("Here you GO!")
        else:
            say(speech)

    def load_response(self):
        self.start_loader()
        _thread.start_new_thread(self.get_response, ())
        #self.get_response()


if __name__ == '__main__':
    window = MyApp()
    window.setWindowFlags(Qt.FramelessWindowHint)
    window.show()
    sys.exit(app.exec())
上面代码中的错误如下所示

QObject:无法为位于不同线程中的父线程创建子线程。
(父线程是QTextDocument(0x19fe090b8c0),父线程是QThread(0x19fde197fb0),当前线程是QThread(0x19fe3a0a5f0)

你认为你能救我吗? 请做!
提前感谢!!

您不必从外部线程更新GUI。有几个选项,如signals、
QMetaObject::invokeMethod(…)
、QEvent和带有pyqtSlot的
QTimer::singleShot(0,…)

使用最后一种方法,解决方案如下:

从functools导入部分
从PyQt5.QtCore导入pyqtlot
类MyApp(QMainWindow):
# ...
@pyqtSlot()
def停止加载器(自身):
self.ui.loader.hide()
self.loading_animate.stop()
def get_响应(自身、文本):
纯文本,语音=获取响应(文本)
QtCore.QTimer.singleShot(0,自停止加载程序)
包装器=部分(self.ui.textDisplay.setText,纯文本)
QtCore.QTimer.singleShot(0,包装器)
如果语音=“”:
说(“给你!”
其他:
说(讲话)
def加载_响应(自身):
self.start_loader()
text=self.ui.queryBox.displayText()
_启动新线程(self.get\u响应,(文本,)

您不必从外部线程更新GUI。有几个选项,如signals、
QMetaObject::invokeMethod(…)
、QEvent和带有pyqtSlot的
QTimer::singleShot(0,…)

使用最后一种方法,解决方案如下:

从functools导入部分
从PyQt5.QtCore导入pyqtlot
类MyApp(QMainWindow):
# ...
@pyqtSlot()
def停止加载器(自身):
self.ui.loader.hide()
self.loading_animate.stop()
def get_响应(自身、文本):
纯文本,语音=获取响应(文本)
QtCore.QTimer.singleShot(0,自停止加载程序)
包装器=部分(self.ui.textDisplay.setText,纯文本)
QtCore.QTimer.singleShot(0,包装器)
如果语音=“”:
说(“给你!”
其他:
说(讲话)
def加载_响应(自身):
self.start_loader()
text=self.ui.queryBox.displayText()
_启动新线程(self.get\u响应,(文本,)