引言
有些时候,我们需要线程进行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
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
# -*- 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
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秒钟
线程的错误用法
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的时候,居然可以正常运行了。
正确用法
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_())



评论 0
还没有评论,来说点什么吧。