pyqt5使用多线程避免程序假死
一、背景
在进行开发的时候,比如请求网页,资源下载等问题的时候 ,需要使用多线程对程序进行处理。一是避免程序假死,二是提高用户体验,增强程序健壮性。
二、方法
通过继承Qthread的方法,重写run函数进行处理。处理的流程如下图
2.1 构建线程方法
通过继承Qthread编写自己的线程方法
# 这里编写一个请求网站资源的多线程方法
class Thread(QThread):
# 设置信号量,用于线程返回信息的处理
signal = pyqtSignal(str)
def __init__(self, url=None):
super(Thread, self).__init__()
# 实现参数的传递
self.url = url
def run(self):
""" 重构的run函数 """
# 需要多线程的方法,这里是一个视频下载的方法
get_url(self.url)
# 将线程处理的信息返回给调用的槽函数,可以实现加锁和解锁的目的
self.signal.emit()
2.2 线程方法的时候
# 在pyqt中使用刚刚创建的线程方法
# 核心部分
# 注:这里使用oop的编程思想,因此输入的文本直接通过文本框的方法获取到输入的结果
def button_ui(self):
# 确定按钮按钮出发线程事件
self.qbtn.clicked.connect(self.event_confirm)
# 按钮布局
self.qbtn.resize(self.qbtn.sizeHint())
self.qbtn.move(189, 400)
# 函数事件
def event_confirm(self):
# 设置按钮不可用,锁定状态
self.qbtn.setEnabled(False)
# 获取参数
content_text = self.qtb.toPlainText()
self.thread.url = content_text
# 启动线程
self.thread.start()
# 处理完之后的回调,
self.thread.signal.connect(self.set_btn)
def set_btn(self):
# 将按钮标签的状态回滚
self.qbtn.setEnabled(True)
2.3 实际例子
这里实现一个从网站下载视频的例子,总代码如下:
import sys
from PyQt5.QtCore import QCoreApplication, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QPlainTextEdit
from PyQt5.QtGui import QIcon
class Thread(QThread):
signal = pyqtSignal(str)
def __init__(self, url=None):
super(Thread, self).__init__()
self.url = url
def run(self):
# 线程使用的方法
get_url(self.url)
self.signal.emit()
class Example(QWidget):
def __init__(self):
super(QWidget, self).__init__()
self.qbtn = QPushButton('确定', self)
self.thread = Thread()
self.qtb = QPlainTextEdit(self, )
self.init_ui() # 界面绘制交给InitUi方法
def button_ui(self):
# 退出按钮
qbtn = QPushButton('退出', self)
qbtn.clicked.connect(QCoreApplication.instance().quit)
qbtn.resize(qbtn.sizeHint())
qbtn.move(689, 400)
# 标签
qlab = QLabel("输入网址", self)
qlab.resize(qlab.sizeHint())
qlab.move(200, 50)
# 输入框
self.qtb.resize(self.qtb.sizeHint())
self.qtb.move(260, 70)
# 确定按钮
self.qbtn.clicked.connect(self.event_confirm)
self.qbtn.resize(self.qbtn.sizeHint())
self.qbtn.move(189, 400)
def event_confirm(self):
self.qbtn.setEnabled(False)
content_text = self.qtb.toPlainText()
self.thread.url = content_text
print(self.thread.url)
self.thread.start()
# print(content_text)
self.thread.signal.connect(self.set_btn)
# content_text = self.qtb.toPlainText()
# self.thread.trigger.connect(get_url(content_text))
# self.thread.start()
def set_btn(self):
self.qbtn.setEnabled(False)
def init_ui(self):
self.button_ui()
# 设置窗口的位置和大小
self.setGeometry(510, 297, 863, 473)
# 设置窗口的标题
self.setWindowTitle('视频获取')
# 设置窗口的图标,引用当前目录下的web.png图片
self.setWindowIcon(QIcon('web.png'))
# 显示窗口
self.show()
if __name__ == '__main__':
# 创建应用程序和对象
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
三、总结
多线程的使用对于实际的开发很重要,这里列举了一个实际的例子,可以据此写出更加复杂的功能。
参考
这里列举一些学习过程中有用的资源。
知乎Qthread多线程多种方法介绍
PyQt关于事件的处理方法