资料

pyqt5 使用多线程避免程序假死 - 蔚蓝色の天空 - 博客园

https://www.cnblogs.com/future-dream/p/14749132.html

需求

在下面这样一个界面,我们希望实现点击按钮1之后,在标签上依次打印 1,2,3,4,…

下面的代码无法实现,因为单线程的原因,只会在标签上打印最后一个数字,且等待时间会出现意思崩溃的假象,因此我们需要使用多线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from PyQt5.Qt import QApplication, QWidget, QPushButton, QLabel
import sys
import time


class MyWinClass(QWidget):
def __init__(self):
super().__init__()

self.btn_1 = QPushButton('按钮1', self)
self.btn_1.move(120, 80)
self.btn_1.clicked.connect(self.btn_1_click)

self.label_1 = QLabel('标签啊标签', self)
self.label_1.move(120, 120)

def btn_1_click(self):
for ii in range(1000):
time.sleep(1)
self.label_1.setText(str(ii))


if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyWinClass()
w.show()
sys.exit(app.exec_())

QThread

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from PyQt5.Qt import QApplication, QWidget, QPushButton, QLabel
from PyQt5.Qt import QThread, pyqtSignal
import sys
import time


class Thread_1(QThread):
signal = pyqtSignal(str)

def run(self):
for ii in range(1000):
time.sleep(1)
self.signal.emit(str(ii))


class MyWinClass(QWidget):
def __init__(self):
super().__init__()

self.btn_1 = QPushButton('按钮1', self)
self.btn_1.move(120, 80)
self.btn_1.clicked.connect(self.btn_1_click)

self.label_1 = QLabel('标签啊标签', self)
self.label_1.move(120, 120)

def btn_1_click(self):
# 实例化一个线程-绑定处理线程信号的函数
self.thread = Thread_1()
self.thread.signal.connect(self.show_msg)
self.thread.start()

def show_msg(self, str00):
""" 处理线程信号的函数 """
self.label_1.setText(str00)


if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyWinClass()
w.show()
sys.exit(app.exec_())
  1. 建立一个继承 QThread 的类 Thread_1,重写 run 函数。在 run 函数中编写耗时或者单线程不便处理的函数,让run函数执行完毕后发出一个信号 signal,在MyWinClass里面编写处理这个信号的函数。
  2. 整个流程的逻辑是:(1) 在主程序中实例化一个 Thread_1 类的线程对象self.thread,(2) 绑定self.thread的槽的处理函数, (3) 执行self.thread.start(),就会执行self.thread.run(),然后发出信号,调用处理槽的函数。
  3. QThread 缺点是不能自己选择终止进程,也可能是我没找到。对于间隔执行的任务,建议使用计时器Qtimer,可以自己选择终止任务。

Qtimer

1
2
3
4
5
6
7
8
9
10
11
12
# Step1 导入模块
from PyQt5.QtCore import QTime

# Step2 在初始化的函数里面添加
self.time = QTimer(self) # 设置一个计时器
self.time.timeout.connect(self.YourFunction) # timeout事件的绑定

# Step3 在开始按钮添加
self.time.start(1000) # 计时开始,单位毫秒

# Step4 在结束按钮添加
self.time.stop() # 计时结束,只有开始状态才能结束