Простая многопоточность с PyQt5, для обновления содержимого QTextBrowser - PullRequest
1 голос
/ 12 апреля 2019

Я нашел в Интернете материал, предполагающий, что виджеты PyQt5 не безопасны для потоков И другие ответы Stackoverflow предлагают создать класс, который подходит только для их проблемы. Я попытался использовать модуль _thread в Python 3, который работает для всего, кроме 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: Cannot create children for a parent that is in a different thread. (Parent is QTextDocument(0x19fe090b8c0), parent's thread is QThread(0x19fde197fb0), current thread is QThread(0x19fe3a0a5f0)

Как вы думаете, вы можете спасти меня? Пожалуйста, сделай ! Заранее спасибо !!

1 Ответ

0 голосов
/ 12 апреля 2019

Вам не нужно обновлять графический интерфейс из внешнего потока. Есть несколько опций, таких как сигналы, QMetaObject::invokeMethod(...), QEvent и QTimer::singleShot(0, ...) с pyqtSlot.

Используя последний метод, решение выглядит следующим образом:

from functools import partial
from PyQt5.QtCore import pyqtSlot

class MyApp(QMainWindow):
    # ...

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

    def get_response(self, text):
        plain_text, speech = get_Wresponse(text)
        QtCore.QTimer.singleShot(0, self.stop_loader)
        wrapper = partial(self.ui.textDisplay.setText, plain_text)
        QtCore.QTimer.singleShot(0, wrapper)
        if speech == '':
            say("Here you GO!")
        else:
            say(speech)

    def load_response(self):
        self.start_loader()
        text = self.ui.queryBox.displayText()
        _thread.start_new_thread(self.get_response, (text,))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...