- 1 多线程QThread
- 1.1 方法列表
- 2 多线程示例
- 2.1 没有使用线程
- 2.2 使用线程,线程有输出信号
- 2.3 使用线程和线程锁,线程有输出信号
- 2.4 使用线程,防止重复触发线程
1 多线程QThread
由于在PyQt5的GUI程序中只存在一个主线程,如果在主线程中进行非常耗时的操作,将会导致GUI界面卡死或者假死,这将十分影响程序的运行。因此后台进行耗时的操作,需要使用线程
1.1 方法列表
QThread的方法 | 说明 |
| 创建线程 |
| 重写 |
| 启动线程 |
| 强制当前线程睡眠多少秒 |
| 在开始执行run函数之前,从相关线程发射此信号 |
| 当程序完成run函数时,从相关线程发射此信号 |
2 多线程示例
2.1 没有使用线程
此例中没有使用线程,操作过程中非常容易卡死,如果不使用QApplication.processEvents()
,文本框中也无法按正常时间显示内容
import sys
from PyQt5.QtWidgets import *
import time
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.move(500, 400)
self.setFixedSize(300, 300)
vlayout = QVBoxLayout()
self.setLayout(vlayout)
text_edit = QTextEdit()
text_edit.setReadOnly(True)
vlayout.addWidget(text_edit)
vlayout.addSpacing(10)
num_button = QPushButton('12345')
num_button.clicked.connect(lambda: self.numPrint(text_edit))
vlayout.addWidget(num_button)
def numPrint(self, text_edit):
for num in '12345':
# 休眠1s
time.sleep(1)
print(num)
text_edit.append(num)
# 在耗时的程序中保持UI刷新
QApplication.processEvents()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
2.2 使用线程,线程有输出信号
此例中使用线程,在线程中print,同时将num通过信号发送给控件。后台与UI独立运行,不会卡顿。
但是线程没有线程锁,多次点击按钮会创建多个独立线程,相互干扰。
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Thread_num(QThread):
# 创建信号,发送str类型数据
num_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
def run(self):
for num in '12345':
# 线程自带休眠方法
self.sleep(1)
print(num)
# 发送信号,num是str类型数据
self.num_signal.emit(num)
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.move(500, 400)
self.setFixedSize(300, 300)
vlayout = QVBoxLayout()
self.setLayout(vlayout)
text_edit = QTextEdit()
text_edit.setReadOnly(True)
vlayout.addWidget(text_edit)
vlayout.addSpacing(10)
num_button = QPushButton('12345')
num_button.clicked.connect(lambda: self.numPrint(text_edit))
vlayout.addWidget(num_button)
def numPrint(self, text_edit):
# 创建线程
self.thread = Thread_num()
self.text_edit = text_edit
# 连接信号
self.thread.num_signal.connect(self.showEdit)
# 线程启动
self.thread.start()
def showEdit(self, num):
self.text_edit.append(num)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
2.3 使用线程和线程锁,线程有输出信号
线程锁让多次点击的并发线程排队,当上一个线程完成后,下一个线程才开始进行
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
# 创建线程锁
qmut = QMutex()
class Thread_num(QThread):
# 创建信号,发送str类型数据
num_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
def run(self):
# 锁住线程
qmut.lock()
for num in '12345':
# 线程自带休眠方法
self.sleep(1)
print(num)
# 发送信号,num是str类型数据
self.num_signal.emit(num)
# 解锁线程
qmut.unlock()
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.move(500, 400)
self.setFixedSize(300, 300)
vlayout = QVBoxLayout()
self.setLayout(vlayout)
text_edit = QTextEdit()
text_edit.setReadOnly(True)
vlayout.addWidget(text_edit)
vlayout.addSpacing(10)
num_button = QPushButton('12345')
num_button.clicked.connect(lambda: self.numPrint(text_edit))
vlayout.addWidget(num_button)
def numPrint(self, text_edit):
# 创建线程
self.thread = Thread_num()
self.text_edit = text_edit
# 连接信号
self.thread.num_signal.connect(self.showEdit)
# 线程启动
self.thread.start()
def showEdit(self, num):
self.text_edit.append(num)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
2.4 使用线程,防止重复触发线程
在线程开始时关闭按钮,线程结束后Enable按钮
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Thread_num(QThread):
# 创建信号,发送str类型数据
num_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
def run(self):
for num in '12345':
# 线程自带休眠方法
self.sleep(1)
print(num)
# 发送信号,num是str类型数据
self.num_signal.emit(num)
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.move(500, 400)
self.setFixedSize(300, 300)
vlayout = QVBoxLayout()
self.setLayout(vlayout)
text_edit = QTextEdit()
text_edit.setReadOnly(True)
vlayout.addWidget(text_edit)
vlayout.addSpacing(10)
num_button = QPushButton('12345')
num_button.clicked.connect(lambda: self.numPrint(num_button, text_edit))
vlayout.addWidget(num_button)
def numPrint(self, num_button, text_edit):
self.num_button = num_button
self.num_button.setEnabled(False)
# 创建线程
self.thread = Thread_num()
self.text_edit = text_edit
# 连接信号
self.thread.num_signal.connect(self.showEdit)
# 连接结束信号
self.thread.finished.connect(self.resetButton)
# 线程启动
self.thread.start()
def showEdit(self, num):
self.text_edit.append(num)
def resetButton(self):
self.num_button.setEnabled(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())