吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1283|回复: 9
收起左侧

[Python 原创] 讨论GUI库pyqt5的中线程通信问题

  [复制链接]
wutljs 发表于 2023-12-2 17:05
本帖最后由 wutljs 于 2023-12-2 19:44 编辑

讨论pyqt5的中线程通信

背景

在使用pyqt5编写GUI程序时,我们可能有时会需要使用多线程来处理问题,这就可能会涉及到线程之间相互通信的问题。比如接下来要解决的进度条问题。

解决思路

我们可以通过pyqt5的信号与槽机制来完成线程之间的通信。

代码编写

# Copyright (C) 2023 - 2023 wutljs, Inc. All Rights Reserved
# @Time: 2023/12/2 10:12
# @Author: wutljs
# @File: item_1.py
# @IDE: PyCharm

import sys, time
from PyQt5.QtCore import QRect, QThread, pyqtSignal
from PyQt5.QtWidgets import QDialog, QProgressBar, QApplication

class UiProgressBarDialog:
    """主线程类"""

    def __init__(self, dialog):
        """做一些简单的初始化工作"""

        self.dialog = dialog  # 获得空dialog
        self.dialog.setFixedSize(480, 360)  # 设置dialog尺寸
        self.progressbar = QProgressBar(self.dialog)  # 添加进度条
        self.progressbar.setGeometry(QRect(80, 80, 351, 31))  # 进设置度条尺寸
        self.progressbar.setValue(0)  # 设置进度初始值为0

    def add_task_thread(self):
        """添加子线程,并建立线程通信(重头戏)"""

        task_thread = TaskThread()  # 添加任务子线程(任务线程)
        task_thread.update_signal.connect(self.update_progressbar)  # 连接子线程(任务线程)信号与主线程的槽,搭建线程通信
        task_thread.start()  # 开启子线程(任务线程)

        self.dialog.exec_()  # dialog开始生效(显示)

    def update_progressbar(self, progressbar_value):
        """槽: 用来接收来自子线程(任务线程)发射的信号,并作出响应(更新进度条)"""
        self.progressbar.setValue(progressbar_value)

class TaskThread(QThread):
    """子线程类"""

    update_signal = pyqtSignal(int)  # 信号: 通知主线程更新进度条的信号
    task_total_num = 1000  # 假设任务总量为1000
    task_finished_num = 0  # 任务完成量

    def do_task(self):
        self.task_finished_num += 1  # 更新任务完成量
        self.update_signal.emit(
            self.task_finished_num / self.task_total_num * 100)  # 子线程(任务线程)发射信号,通知主线程更新进度条的值为此信号所携带的值.

    def run(self):
        # 模拟完成任务
        for i in range(self.task_total_num):
            self.do_task()  # 模拟做任务
            time.sleep(0.001)  # 防止进度条更新过快不便于观察

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = UiProgressBarDialog(QDialog())
    ui.add_task_thread()

运行结果

进度条.gif

结论

当我们使用pyqt5进行可视化编程时,或许我们总能碰到主线程卡死的情况。除了代码编写的有问题,有一种可能就是有一些非常耗时、占用资源的代码在运行时阻塞着主线程,故此时需要使用多线程的方法来解决问题。而在代码中,我们看到使用信号与槽这一机制可以很好地完成线程之间的通信问题。

展望

显然,这个程序有着很强的可扩展性:

  • 将TaskThread的run方法抽离出来,把这个进度条代码变成装饰器,可以很方便的看到被修饰代码运行进度。
  • 这段代码可以与异步协程结合。使用协程解决的问题一般都是任务量比较大的问题,正好可以用进度条来记录当前任务进度。不过如果真有此打算的话,代码还需要补充一些必要的东西,碰巧笔者有一些经验,欢迎探讨。
  • 将这个进度条的UI使用html、js或者css润色加工一下,放在项目中感觉也还可以。

除此以外,信号与槽机制的应用显然不止这些,感兴趣的朋友可以自行探索~

参考文章

PyQt5——信号与槽函数

pyqt5多线程模块QThread的使用方法

免费评分

参与人数 4吾爱币 +11 热心值 +3 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
aqin5014 + 1 用心讨论,共获提升!
lccccccc + 1 + 1 我很赞同!
qianshang666 + 2 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| wutljs 发表于 2023-12-4 11:54
lookfeiji 发表于 2023-12-4 10:57
不对,不是线程问题,是多线程的机制与通信的问题,tkinter没提供多线程的方法,python的多线程都被说是 ...

确实,python因为GIL缘故不像java那样可以搞多线程(Hadoop等框架都是java写的)。
pyqt5可以解决您的问题,查相关文档即可~
aqin5014 发表于 2023-12-3 10:34
Cacarot 发表于 2023-12-3 17:54
一个时间倒数子线程CPU占用过高,看看有没有帮助
 楼主| wutljs 发表于 2023-12-3 18:12
aqin5014 发表于 2023-12-3 10:34
最近刚好在学习这个,支持你一波

谢谢啦,祝你顺利!
 楼主| wutljs 发表于 2023-12-3 20:28
本帖最后由 wutljs 于 2023-12-3 20:30 编辑
Cacarot 发表于 2023-12-3 17:54
一个时间倒数子线程CPU占用过高,看看有没有帮助

嗯~这篇文章的逻辑是将耗时任务放在子线程,防止主线程卡死。线程间交互的方式为信号与槽机制~
如果该耗时任务真的很棘手,建议使用节点分布式等手段完成。
lookfeiji 发表于 2023-12-4 08:36
收下代码先,我在tkinter上也碰到了这个问题,但是遗憾的是我没找到解决办法,最后放弃用进度条了
 楼主| wutljs 发表于 2023-12-4 09:14
lookfeiji 发表于 2023-12-4 08:36
收下代码先,我在tkinter上也碰到了这个问题,但是遗憾的是我没找到解决办法,最后放弃用进度条了

嗯,之前我尝试使用threading开线程作为子线程,但依然使主线程处于假死的状态。后来使用pyqt5中特有的线程通信机制才解决了问题。tkinter没怎么接触过,不过您可以试试tkinter提供的多线程方法?
lookfeiji 发表于 2023-12-4 10:20
wutljs 发表于 2023-12-4 09:14
嗯,之前我尝试使用threading开线程作为子线程,但依然使主线程处于假死的状态。后来使用pyqt5中特有的线 ...

谢谢,你这给了我一个很好的提示,我问gpt他说tkinter没有多线程方法,但是我在百度居然搜到了,研究研究去
lookfeiji 发表于 2023-12-4 10:57
wutljs 发表于 2023-12-4 09:14
嗯,之前我尝试使用threading开线程作为子线程,但依然使主线程处于假死的状态。后来使用pyqt5中特有的线 ...

不对,不是线程问题,是多线程的机制与通信的问题,tkinter没提供多线程的方法,python的多线程都被说是假的,主要没法实现线程与线程之间的通信,还有就是基本的线程关闭,以及线程与主线程之间的调度都有点难搞
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 17:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表