@ pyqt5
When running a program with multi-threaded pyqt5, if the program takes too long, the interface will freeze. The solution can be to put the program that takes too long into the thread.
One, rewrite the QThread class
#需要加载模块中的QThread和pyqtSignal
from PyQt5.QtCore import QThread,pyqtSignal
class MyThread(QThread):
Signal1 = pyqtSignal(str) #自定义触发信号
def __init__(self, count):
super().__init__()
self.count = count
def run(self): #run方法重写
for i in range(self.count):
self.Signal1.emit(str(i)) #发送信号,触发槽函数
time.sleep(1) #添加时延
1. Custom trigger signal
The pyqtSignal() custom trigger signal is a class variable, and the parameter type can be str, int, None, list and other forms to indicate the signal type of the trigger.
2,run()
Override the run() method in a custom thread class. The thread function written in the run() method is generally a function that takes a long time or is executed repeatedly.
3,emit()
emit() is used to trigger the slot function. The parameter type is the same as the parameter type of pyqtSignal(), indicating the type of trigger signal. The parameters of emit() will be passed to the slot function connected to this signal.
4. On the importance of time delay
When I first looked at other people's introductions, I didn't understand why I had to add a delay at the end. I didn't understand the importance of delay until my program was executed and the interface suspended animation after adding multiple threads.
If the thread function triggers the slot function as a loop trigger, and the running time in each loop is too short, the thread frequently triggers the slot function and the interval of accessing the main interface is too short, it will appear that the main interface runs all the time and the interface freezes.
Second, thread execution
self.Thread1 = MyThread(10) #创建线程实例
self.Thread1.Signal1.connect(self.threadFunc) #自定义的信号连接到槽函数
self.Thread1.start() #开始执行
1. First, instantiate, create a thread instance, and initialize it.
2. When the thread executes, it still follows the signal and slot function mechanism of qt. By rewriting the custom trigger signal in the Qthread class, the thread triggers the Signal1 signal and connects to the slot function threadFunc. The slot function interacts with the interface, that is, the function is separated from the UI , The execution function part in the run() function, and the interface interaction in the slot function. Thread and slot function passing parameters are passed through the emit() trigger function.
3. When start() is executed, the thread starts to execute, and the run() function in the thread class will be executed automatically.
Three, timing
The main thread executes, executes to the start() of the child thread, the main thread continues to execute, and the child thread automatically jumps to the run() function to perform the function of the child thread. Until emit() triggers the signal to the threadFun slot function, interacts with the UI, and returns to the main thread. At this time, if the execution of the main thread code segment is completed, the slot function is executed. The main thread code segment has not been executed, and the slot function is executed after the main thread code segment is executed.
Four, code examples
Post a code record you wrote casually
import time
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import QThread,pyqtSignal
from PyQt5.QtSerialPort import QSerialPortInfo
from TestUI import Ui_Form #UI
#自定义线程类省略
#界面交互
class QmyMainWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
# self.setupUi()
self.Ui_Form = Ui_Form()
self.Ui_Form.setupUi(self)
# 禁用最大化和窗口拉伸
self.setFixedSize(self.width(),self.height())
def closeEvent(self, event):
reply = QMessageBox.question(self, 'Information',"Are you sure to quit?", QMessageBox.Yes|QMessageBox.No, QMessageBox.Yes)
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()
def threadFunc(self,content):#线程槽函数
self.Ui_Form.lineEdit.setText(content)
return
def thread1(self):#UI按键槽函数
self.Thread1 = MyThread(10)
self.Thread1.Signal1.connect(self.threadFunc)
self.Thread1.start()
def thread2(self):#UI按键槽函数
self.Thread2 = MyThread(20)
self.Thread2.Signal1.connect(self.threadFunc)
self.Thread2.start()
if __name__=="__main__":
app = QApplication(sys.argv)
MainWin = QmyMainWindow()
MainWin.show()
sys.exit(app.exec_())
#Qt designer生成的UI TestUI.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(530, 471)
self.lineEdit = QtWidgets.QLineEdit(Form)
self.lineEdit.setGeometry(QtCore.QRect(100, 180, 331, 21))
self.lineEdit.setObjectName("lineEdit")
self.Run = QtWidgets.QPushButton(Form)
self.Run.setGeometry(QtCore.QRect(120, 260, 93, 28))
self.Run.setObjectName("Run")
self.Stop = QtWidgets.QPushButton(Form)
self.Stop.setGeometry(QtCore.QRect(310, 260, 93, 28))
self.Stop.setObjectName("Stop")
self.retranslateUi(Form)
self.Run.clicked.connect(Form.thread1)
self.Stop.clicked.connect(Form.thread2)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.Run.setText(_translate("Form", "Thread1"))
self.Stop.setText(_translate("Form", "Thread2"))
Effect picture