Loading... # 引言 有些时候,我们需要线程进行UI操作,因为主线程在执行耗时操作的时候,UI会卡死,导致程序进入假死状态,这时候应当考虑线程操作UI,但是非UI线程操作UI是不被允许的,这时候就需要定义一个信号量,通知主线程修改UI。 # 定义启动类 ## 结构说明 bootstrap.py 启动器 main.ui ui文件 main.py ui转换成的py文件 ## 启动器类 一般情况下,我们使用qtdesigner进行UI设计,通过PyUIC转成py源码,但是如果我们UI并不能一次性设计好,并且需要绑定槽和一系列操作,就不能修改UIC后的文件,因为一旦重新ui生成py文件,那就会把之前的代码清除掉,所以在这里我们需要再定义一个类,暂且叫作bootstrap.py ```python class my_window(main.UI_MainWindow): # main.UI_MainWindow 就是main.py中的Ui_MainWindow类 def __init__(self): super(window,self) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) MainWindow = Dialog() ui = window() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_()) ``` 这时候,我们继承了main.py,就可以随心所欲的健壮我们的代码了。 # 线程操作 ## 不使用线程操作 > main.py ```python # -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'main2.ui' # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(336, 310) MainWindow.setWindowTitle("") MainWindow.setStyleSheet("color:white") self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setObjectName("pushButton") self.gridLayout.addWidget(self.pushButton, 1, 0, 1, 1) self.lcdNumber = QtWidgets.QLCDNumber(self.centralwidget) self.lcdNumber.setSmallDecimalPoint(False) self.lcdNumber.setDigitCount(10) self.lcdNumber.setProperty("intValue", 2) self.lcdNumber.setObjectName("lcdNumber") self.gridLayout.addWidget(self.lcdNumber, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate self.pushButton.setText(_translate("MainWindow", "PushButton")) ``` > bootstrap.py ```python import sys import time from PyQt5 import QtWidgets from PyQt5.QtCore import QTimer import main class my_window(main.Ui_MainWindow): def __init__(self): super(my_window, self) def click(self): time.sleep(1) self.lcdNumber.display(self.lcdNumber.intValue() + 1) def interval(self): self.lcdNumber.display(self.lcdNumber.intValue() + 1) def initialize(self): self.q_timer = QTimer() # 一定要用self,不然不生效,这也就是为什么用继承的原因 self.q_timer.timeout.connect(self.interval) self.q_timer.start(100) self.pushButton.clicked.connect(self.click) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = my_window() ui.setupUi(MainWindow) ui.initialize() MainWindow.show() sys.exit(app.exec_()) ``` 当点击按钮的时候,UI会卡死1秒钟 ## 线程的错误用法 ```python import sys import threading import time from PyQt5 import QtWidgets from PyQt5.QtCore import QTimer import main2 class my_window(main2.Ui_MainWindow): def __init__(self): super(my_window, self) def click(self): print("Click") time.sleep(1) self.lcdNumber.display(self.lcdNumber.intValue() + 1000) print("Done") def interval(self): self.lcdNumber.display(self.lcdNumber.intValue() + 1) def mythread(self): threading.Thread(target=self.click).start() def initialize(self): self.q_timer = QTimer() self.q_timer.timeout.connect(self.interval) self.q_timer.start(100) self.pushButton.clicked.connect(self.mythread) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = my_window() ui.setupUi(MainWindow) ui.initialize() MainWindow.show() sys.exit(app.exec_()) ``` 这种用法可能会导致`Process finished with exit code -1073740791 (0xC0000409)`,很奇怪,之前的代码这样做出现过这个报错,但是写Demo的时候,居然可以正常运行了。 ## 正确用法 ```python import sys import threading import time from PyQt5 import QtWidgets from PyQt5.QtCore import QTimer, QThread, pyqtSignal import main2 class my_thread(QThread): update_ui_signal = pyqtSignal(int) def __init__(self): super(my_thread, self).__init__() def run(self): for i in range(1, 1000): self.update_ui_signal.emit(1) class my_window(main2.Ui_MainWindow): def __init__(self): super(my_window, self) def update_ui_function(self, n): self.lcdNumber.display(n + self.lcdNumber.intValue()) def click(self): self.thread = my_thread() self.thread.update_ui_signal.connect(self.update_ui_function) self.thread.start() def interval(self): self.lcdNumber.display(self.lcdNumber.intValue() + 1) def initialize(self): self.q_timer = QTimer() self.q_timer.timeout.connect(self.interval) self.q_timer.start(100) self.pushButton.clicked.connect(self.click) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = my_window() ui.setupUi(MainWindow) ui.initialize() MainWindow.show() sys.exit(app.exec_()) ``` ![image.png](https://www.zunmx.top/usr/uploads/2023/06/1715780599.png) © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 1 如果觉得我的文章对你有用,请随意赞赏