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

时间:2019-04-12 17:57:28

标签: python python-3.x pyqt pyqt5

我在网上发现了一些东西,表明PyQt5小部件不是线程安全的。 其他Stackoverflow答案建议创建一个仅适合其问题的类。我尝试在Python 3中使用import pandas as pd from pandas import read_excel, read_csv import openpyxl as px from openpyxl import Workbook, load_workbook, cell import numpy as np from openpyxl.compat import range from openpyxl.utils.dataframe import dataframe_to_rows a = load_workbook(r"C:\Users\45050393\Documents\libro_vacio.xlsm", keep_vba = True) df = pd.DataFrame({1 : [23, 34, 56, 78, 89, 12, 48]}) print(df) ws = a.active hoja_a_marcar = a.get_sheet_by_name("Sheet1") startcol = ws["H2":"H8"] hoja_a_marcar.cell(row = 3, column = 4).value for r in dataframe_to_rows(df, index = False, header = False): for rows in startcol: ws.append(r) print("HECHO") a.save(filename= r"C:\Users\45050393\Documents\libro_vacio.xlsm") 模块,该模块适用于除PyQt之外的所有模块。

_thread

随后出现上述代码中的错误

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())

您认为您可以救我吗? 请做! 在此先感谢!

1 个答案:

答案 0 :(得分:0)

您不必从外部线程更新GUI。带有pyqtSlot的信号有QMetaObject::invokeMethod(...),QEvent和QTimer::singleShot(0, ...)之类的几个选项。

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

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,))