PyQt5第八部分-多线程-QThread

0 前言

>>返回Python系列文章目录<<

1 多线程QThread

由于在PyQt5的GUI程序中只存在一个主线程,如果在主线程中进行非常耗时的操作,将会导致GUI界面卡死或者假死,这将十分影响程序的运行。因此后台进行耗时的操作,需要使用线程

1.1 方法列表

QThread的方法说明
self=QThread()创建线程
def run(self):重写run方法定义线程的工作内容
self.start()启动线程
self.sleep(n)强制当前线程睡眠多少秒
self.started.connect(fun)在开始执行run函数之前,从相关线程发射此信号
self.finished.connect(fun)当程序完成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_())

在这里插入图片描述
>>返回Python系列文章目录<<

  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值