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关于事件的处理方法