Pyqt5实现新线程更新窗口UI

Pyqt5实现线程内更新窗口UI

我们用pyqt5开发窗口应用时,应用会执行一些耗时的操作,如复制大量文件,下载大量数据等。一般情况下,在这些操作没有完成时,窗口的UI处于“假死”状态,不会更新,只有所有操作完成后,窗口的状态才会更新。这样对用户使用非常不友好。
使用多线程技术,在新线程内进行那些耗时的操作,同时根据操作进度向主线程返回操作进度,根据进度更新窗口UI,可以实现更好的用户体验。

下面是用一个简单的例子说明实现过程。

一、程序界面:

程序界面如下:
在这里插入图片描述

本例中,窗口有一个按钮和一个多行文本框。点击按钮后开启新线程,进行耗时操作。在点击后修改按钮的状态为不可用,可以防止用户重复点击,新线程将完成进度返回给主线程,根据完成进度,更新文本框的内容用于显示完成进度。待操作全部完成后,新线程返回“全部完成”,主线程恢复按钮的状态为可用。

二、实现代码:

'''
code writing:hnkkfan
本例用于演示Pyqt5 在线程中更新UI控件
窗口中使用一个多行文本框QTextEdit,用于显示更新的处理线程进度
一个按钮QPushButton,点击开始后开始在新线程中处理耗时比较长的工作
为防止重复操作,在点击按钮后的处理过程中,按钮的状态变为不可用,
处理完成后,恢复状态为可用。
'''

from PyQt5.Qt import (QApplication, QWidget, QPushButton,QThread,pyqtSignal)
import sys
import time
from PyQt5.QtWidgets import QTextEdit, QHBoxLayout, QVBoxLayout


class Thread_do(QThread):  # 定义线程类
    _signal =pyqtSignal(str)#定义带参数一个信号
    def __init__(self):
        super().__init__()

    def run(self):#线程的执行方法
        for i in range(20):
            retInfo=f"开始处理第{i+1}个..."
            time.sleep(0.5)#这个用休眠0.5秒代替我们需要执行的耗进代码
            retInfo+="处理完成"
            self._signal.emit(retInfo)#返回进度
        self._signal.emit("全部完成")#循环结束后返回全部完成

class MyWin(QWidget):
    def __init__(self):
        super().__init__()
        self.txt_PressInfo = QTextEdit()  # 定义一个处理信息文本框
        self.btn_do = QPushButton('开始处理', self)#定义一个按钮
        self.btn_do.clicked.connect(self.btn_click)  # 绑定槽函数
        #定义两个水平布局,用于放置文本框和按钮
        hbox_line1 = QHBoxLayout()
        hbox_line1.addWidget(self.txt_PressInfo)
        hbox_line2 = QHBoxLayout()
        hbox_line2.addWidget(self.btn_do)
        #定义一个垂直布局用于放置两个水平布局
        vbox = QVBoxLayout()
        vbox.addLayout(hbox_line1)
        vbox.addLayout(hbox_line2)  # 添加上面的水平布局器

        self.setLayout(vbox)  # 把垂直布局器添加到窗口
    def btn_click(self):#按钮的点击事件
        #点击后让按钮不可用,防止重复点击,并改变按钮文本为正在处理...
        self.btn_do.setEnabled(False)
        self.btn_do.setText("正在处理...")
        #定义线程实例
        self.thread_do = Thread_do()
        # 信号连接,如果收到信号,就执行对应的函数
        self.thread_do._signal.connect(self.set_btn_resig)
        #启动线程实例
        self.thread_do.start()

    #定义收到信号的处理方法
    def set_btn_resig(self,_info):
        if _info=="全部完成":#如果返回值为全部完成则恢复按钮的状态和文本
            self.btn_do.setEnabled(True)
            self.btn_do.setText("开始处理")
        else:#否则在文本框中显示进度
            self.txt_PressInfo.append(_info)



if __name__ == "__main__":
    app = QApplication(sys.argv)
    myshow = MyWin()
    myshow.setWindowTitle("多线程更新UI演示")
    myshow.setMinimumHeight(480)
    myshow.setMinimumWidth(640)
    myshow.show()
    sys.exit(app.exec_())

三、运行效果:

点击后,按钮不可用,并修改按钮文本为“正在处理…”。同时新线程不断向主线程返回进度,并更新文本框中的进度信息。
在这里插入图片描述

全部操作执行完毕后,新线程向主线程返回“全部完成”,主线程收到信息后,将按钮状态变为可用,并将按钮的文本改回“开始处理”
在这里插入图片描述

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyQt5 UI 界面分为多线程任务可以通过使用 Python 的 `threading` 模块来实现。以下是一个简单的示例代码,演示了如何在 PyQt5 应用程序中使用多线程任务: ```python import sys import time import threading from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel class MainWindow(QMainWindow): def __init__(self): super().__init__() self.label = QLabel('Waiting for task to finish...', self) self.setCentralWidget(self.label) self.thread = threading.Thread(target=self.do_task) self.thread.start() def do_task(self): time.sleep(5) # 模拟耗时任务 self.label.setText('Task is finished.') if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` 在上面的示例代码中,我们创建了一个 `MainWindow` 类,它继承自 `QMainWindow`。在 `MainWindow` 的构造函数中,我们创建了一个 `QLabel` 对象,并将其设置为中心窗口小部件。然后,我们创建了一个线程对象,并将其目标设置为 `do_task` 方法。最后,我们启动线程。 在 `do_task` 方法中,我们模拟了一个耗时任务,即睡眠了 5 秒钟,然后将标签文本设置为“任务已完成”。 当我们运行这个示例代码时,我们会看到一个窗口出现,上面显示着“等待任务完成”的文本。然后,5 秒钟后,文本变为“任务已完成”。在这个过程中,我们的应用程序仍然可以响应用户的输入,因为任务正在另一个线程中运行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值