【无标题】PySide6在非UI线程更新UI界面实例

这篇具有很好参考价值的文章主要介绍了【无标题】PySide6在非UI线程更新UI界面实例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第一种:直接使用QThread类更新UI界面

        写一个SonThread类继承于QThread,直接在run函数中写我们要执行的动作(更新UI界面)。优点比较简单易懂,缺点只能被一种事件使用,不能重复利用。

# -*- coding: utf-8 -*-

import sys
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import QApplication, QWidget, QTextBrowser, QPushButton, QHBoxLayout

# 创建QApplication对象
if not QApplication.instance():
    app = QApplication([])
else:
    app = QApplication.instance()


class SonThread(QThread):
    """子线程"""

    update_date = Signal(str)  # 定义信号

    def __init__(self, data):
        """子线程初始化"""
        super().__init__()  # 初始化父级
        self.result = data  # 把传入的参数data赋值给类变量result

    def run(self):
        """子线程执行时执行此函数"""
        for i in range(5):
            self.update_date.emit(str(f"倒计时:{5-i}"))  # 发送信号,信号内容为(倒计时:5-i)
            time.sleep(1)  # 延时1秒(不管延时多久,UI界面都不会出现假死状态)
        self.update_date.emit(str(self.result))  # 发送信号,信号内容为类变量result


class MyWindow(QWidget):
    """UI线程"""

    def __init__(self):
        """UI线程初始化"""
        super().__init__()  # 初始化父级
        self.son_thread = None  # 创建子线程变量
        self.setWindowTitle('子线程更新UI线程实例')  # 设置窗口标题
        self.text = QTextBrowser()  # 定义文本浏览框
        self.button = QPushButton("发送信号")  # 定义按钮
        self.main_layout = QHBoxLayout(self)  # 定义水平布局容器
        self.main_layout.addWidget(self.text)  # 布局文本浏览框
        self.main_layout.addWidget(self.button)  # 布局按钮
        self.button.clicked.connect(self.send_sign)  # 按钮点击事件绑定(send_sign)函数

    def send_sign(self):
        """点击按钮时执行此函数"""
        self.son_thread = SonThread("hello everyone")  # 定义子线程并传入参数(hello everyone)
        self.son_thread.update_date.connect(self.add_text)  # 给信号绑定(add_text)函数
        self.son_thread.start()  # 执行子线程

    def add_text(self, data):
        """
        收到信号时执行此函数
        :param data: 信号内容
        :return:
        """
        self.text.append(data)  # 在文本浏览框中追加内容(data)


def main():
    widget = MyWindow()  # 实例化UI线程
    widget.resize(300, 200)  # 设置窗口大小
    widget.show()  # 展示窗口
    sys.exit(app.exec())  # 持续刷新窗口


if __name__ == '__main__':
    main()

第二种:在其他线程中使用QThread类更新UI界面

        使用threading来创建新线程,在新线程中使用SonThread来更新UI界面。只用写一个更新UI界面的类,可以被很多的事件使用。

# -*- coding: utf-8 -*-

import sys
import threading
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import QApplication, QWidget, QTextBrowser, QPushButton, QHBoxLayout, QVBoxLayout

# 创建QApplication对象
if not QApplication.instance():
    app = QApplication([])
else:
    app = QApplication.instance()


def thread_ui(func, *args):
    """
    开启一个新线程任务
    :param func: 要执行的线程函数;
    :param args: 函数中需要传入的参数 Any
    :return:
    """
    t = threading.Thread(target=func, args=args)  # 定义新线程
    t.setDaemon(True)  # 开启线程守护
    t.start()  # 执行线程


class SonThread(QThread):
    """子线程"""

    update_date = Signal(str)  # 定义信号

    def __init__(self, data):
        """子线程初始化"""
        super().__init__()  # 初始化父级
        self.result = data  # 把传入的参数data赋值给类变量result

    def run(self):
        """子线程执行时执行此函数"""
        self.update_date.emit(str(self.result))  # 发送信号,信号内容为类变量result


class MyWindow(QWidget):
    """UI线程"""

    def __init__(self):
        """UI线程初始化"""
        super().__init__()  # 初始化父级
        self.son_thread = None  # 创建子线程变量
        self.setWindowTitle('子线程更新UI线程实例')  # 设置窗口标题
        self.text = QTextBrowser()  # 定义文本浏览框
        self.button = QPushButton("发送信号")  # 定义发送信号按钮
        self.clear_button = QPushButton("清除文本")  # 定义清除文本按钮
        self.main_layout = QHBoxLayout(self)  # 定义水平布局容器
        self.son_layout = QVBoxLayout()  # 定义垂直布局容器
        self.main_layout.addWidget(self.text)  # 布局文本浏览框
        self.main_layout.addLayout(self.son_layout)  # 布局垂直布局容器
        self.son_layout.addWidget(self.button)  # 布局发送信号按钮
        self.son_layout.addWidget(self.clear_button)  # 布局清除文本按钮
        self.button.clicked.connect(self.button_click)  # 发送信号按钮点击事件绑定(button_click)函数
        self.clear_button.clicked.connect(self.clear_click)  # 清除文本按钮点击事件绑定(clear_click)函数

    def button_click(self):
        """点击发送信号按钮时执行此函数"""
        def button_thread():
            for i in range(5):
                self.send_sign(f"倒计时:{5-i}")  # 发送信号(倒计时:{5-i})
                time.sleep(1)  # 延时1秒(不管延时多久,UI界面都不会出现假死状态)
            self.send_sign("你好啊")  # 发送信号(你好啊)
        return thread_ui(button_thread)  # 开启新线程来执行(button_thread)函数

    def clear_click(self):
        """点击清除文本按钮时执行此函数"""
        def clear_text():
            for i in range(5):
                self.send_sign(f"倒计时:{5 - i}")  # 发送信号(倒计时:{5-i})
                time.sleep(1)  # 延时1秒(不管延时多久,UI界面都不会出现假死状态)
            self.send_sign("clear")  # 发送信号(clear)
        return thread_ui(clear_text)  # 开启新线程来执行(clear_text)函数

    def send_sign(self, data):
        """
        使用SonThread发送信号
        :param data: 发送的内容
        :return:
        """
        self.son_thread = SonThread(data)  # 定义子线程并传入参数(data)
        self.son_thread.update_date.connect(self.add_text)  # 给信号绑定(add_text)函数
        self.son_thread.start()  # 执行子线程

    def add_text(self, data):
        """
        收到信号时执行此函数
        :param data: 接收的内容
        :return:
        """
        if data == 'clear':  # 判断接收的内容是否为clear
            self.text.clear()  # 是clear就清空文本框内容
        else:  # 不是clear
            self.text.append(data)  # 在文本浏览框中追加内容(data)


def main():
    widget = MyWindow()  # 实例化UI线程
    widget.resize(300, 200)  # 设置窗口大小
    widget.show()  # 展示窗口
    sys.exit(app.exec())  # 持续刷新窗口


if __name__ == '__main__':
    main()

 第三种:创建信号线程(最优)

        鉴于前面两种方式,都有一些问题,后来我想到了第三种方式。这种方式可以使用一个信号类实例化出多个信号对象,每个信号都绑定一个的方法,每个信号都是独立存在的。我们同时可以发送多种信号去影响一个UI元素,而且每个信号之间都不会发生干扰。

# -*- coding: utf-8 -*-

import sys
import threading
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import QApplication, QWidget, QTextBrowser, QPushButton, QHBoxLayout, QVBoxLayout, QMessageBox

# 创建QApplication对象
if not QApplication.instance():
    app = QApplication([])
else:
    app = QApplication.instance()


def thread_ui(func, *args):
    """
    开启一个新线程任务\n
    :param func: 要执行的线程函数;
    :param args: 函数中需要传入的参数 Any
    :return:
    """
    t = threading.Thread(target=func, args=args)  # 定义新线程
    t.setDaemon(True)  # 开启线程守护
    t.start()  # 执行线程


class SignThread(QThread):
    """信号线程"""

    def __new__(cls, parent: QWidget, func, *types: type):
        cls.update_date = Signal(*types)  # 定义信号(*types)一个信号中可以有一个或多个类型的数据(int,str,list,...)
        return super().__new__(cls)  # 使用父类__new__方法创建SignThread实例对象

    def __init__(self, parent: QWidget, func, *types: type):
        """
        信号线程初始化\n
        :param parent: 界面UI控件
        :param func: 信号要绑定的方法
        :param types: 信号类型,可以是一个或多个(type,...)
        """
        super().__init__(parent)  # 初始化父类
        self.sign = None
        self.update_date.connect(func)  # 绑定信号与方法

    def send_sign(self, *args):
        """
        使用SonThread发送信号\n
        :param args: 信号的内容
        :return:
        """
        self.sign = args  # 信号元组(type,...)
        self.start()

    def run(self):
        """信号线程执行时执行此函数"""
        self.update_date.emit(*self.sign)  # 发送信号元组(type,...)


class MyWindow(QWidget):
    """UI界面"""

    def __init__(self):
        """UI界面初始化"""
        super().__init__()  # 初始化父级
        self.setWindowTitle('子线程更新UI线程实例')  # 设置窗口标题
        self.text = QTextBrowser()  # 定义文本浏览框
        self.button = QPushButton("添加文本")  # 定义发送信号按钮
        self.clear_button = QPushButton("清除文本")  # 定义清除文本按钮
        self.main_layout = QHBoxLayout(self)  # 定义水平布局容器
        self.son_layout = QVBoxLayout()  # 定义垂直布局容器
        self.main_layout.addWidget(self.text)  # 布局文本浏览框
        self.main_layout.addLayout(self.son_layout)  # 布局垂直布局容器
        self.son_layout.addWidget(self.button)  # 布局发送信号按钮
        self.son_layout.addWidget(self.clear_button)  # 布局清除文本按钮
        self.button.clicked.connect(self.button_click)  # 发送信号按钮点击事件绑定(button_click)函数
        self.clear_button.clicked.connect(self.clear_click)  # 清除文本按钮点击事件绑定(clear_click)函数
        self.add_thread = SignThread(self, self.add_text, str, int)  # 创建信号线程,并绑定add_text函数,信号使用str和int两种数据
        self.clear_thread = SignThread(self, self.clear_text, int)  # 创建信号线程,并绑定clear_text函数,信号只使用int数据

    def button_click(self):
        """点击发送信号按钮时执行此函数"""
        def button_thread():
            for i in range(5):
                self.add_thread.send_sign(f"添加倒计时:{5-i}", i)  # 发送信号(倒计时:{5-i}, i)
                time.sleep(1)  # 延时1秒(不管延时多久,UI界面都不会出现假死状态)
            self.add_thread.send_sign('你好啊', 99)  # 发送信号(你好啊, 99)
        return thread_ui(button_thread)  # 开启新线程来执行(button_thread)函数

    def clear_click(self):
        """点击清除文本按钮时执行此函数"""
        def clear_text():
            for i in range(5):
                self.clear_thread.send_sign(0)  # 发送信号(0)
                time.sleep(1)  # 延时1秒(不管延时多久,UI界面都不会出现假死状态)
            self.clear_thread.send_sign(1)  # 发送信号(1)
        return thread_ui(clear_text)  # 开启新线程来执行(clear_text)函数

    def add_text(self, *args):
        """
        收到add_thread信号时执行此函数\n
        :param args: 接收的信号元组
        :return:
        """
        self.text.append(f'str: {args[0]} int: {args[1]}')  # 在文本浏览框中追加内容(data)

    def clear_text(self, *args):
        """
        收到clear_thread信号时执行此函数\n
        :param args: 接收的信号元组
        :return: 
        """
        self.text.clear()  # 清除文本浏览框中的内容
        if args[0] == 1:  # 当信号元组的第一个元素为整型1时
            msg = QMessageBox(self)
            msg.setText(f"清除文本结束")
            msg.exec()


def main():
    widget = MyWindow()  # 实例化UI线程
    widget.resize(300, 200)  # 设置窗口大小
    widget.show()  # 展示窗口
    sys.exit(app.exec())  # 持续刷新窗口


if __name__ == '__main__':
    main()

在这个实例中,我们可以同时点击添加文本和清除文本按钮,让文本框一边添加文本一边删除文本,两个信号差不多同时进行,互不影响。文章来源地址https://www.toymoban.com/news/detail-595413.html

到了这里,关于【无标题】PySide6在非UI线程更新UI界面实例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Pyside6 安装和简单界面开发

    对于Python的GUI开发来说,Python自带的可视化编程模块的功能较弱,PySide是跨平台应用程序框架Qt的Python绑定,Qt是跨平台C++图形可视化界面应用开发框架,自推出以来深受业界盛赞。PySide由Qt公司自己维护,允许用户在Python环境下利用Qt开发大型复杂GUI。用Python简洁的语法调用

    2024年02月07日
    浏览(32)
  • Pyside6:加载.ui

    通常来说开发Qt的界面基本都在Qt Designer中进行的,它保存的文件为.ui,我们可以通过uic将其转变为.py文件(如何使用:Pyside6:安装及Pycharm配置_pyside6安装pycharm-CSDN博客)。 那么该如何进行加载呢?大致来说有两种方法: 这个非常简单,无需把.ui文件进行转换,但 loader.loa

    2024年02月03日
    浏览(34)
  • PySide6 拖拖拽拽完成图形界面设计

    Designer是PySide6 程序UI界面的实现工具,Designer工具使用简单,可以通过拖拽和点击完成复杂界面设计,并且设计完成的.ui程序可以转换成.py文件供python程序调用。 使用Designer构建你的UI。 Designer是一个功能强大的图形用户界面设计器,可让您在不编写代码的情况下创建和配置表

    2024年02月15日
    浏览(56)
  • PySide6 将.ui文件编译为.py文件

    1. 制作UI 平时使用QT creator设计器设计UI,然后可将其转化成 .py 文件,以供 .py 脚本使用。 2.Pyside6 转换ui为 .py 文件 pyside6使用过程: 生成的py文件: 3. .py 文件国际化 通过pyside6-uic生成的 .py 代码中,中文或文本将使用unicode表示,即:“机器人设置”(u\\\"u673au5668u4ebau8bbeu

    2024年02月12日
    浏览(40)
  • 使用pyside6将ui文件转换为py

    在MainWindow.ui文件所在文件夹搜索栏输入cmd,点击回车键; 示意图如下: 直接输入下述代码: 示意图如下:

    2024年04月23日
    浏览(23)
  • PySide6:Qt Designer UI文件的两种使用方式

    通过Qt Designer(PyQt6与PySide6对应的Designer设计的界面生成的UI文件有区别)设计的界面会生成对应的UI文件,一般会使用PyUIC工具将UI文件转换为对应的Py文件来使用,后面每次界面发生更新时都要重新转换一次,比较麻烦;另外,如果直接在UI文件中添加自己的代码,如信号与槽

    2024年02月11日
    浏览(35)
  • Python学习笔记——PySide6设计GUI应用之UI与逻辑分离

    1、打开PySide6的UI设计工具pyside6-designer,设计一个主窗口,保存文件名为testwindow.ui 2、使用PySide6的RCC工具把testwindow.ui文件转换为testwindow_rc.py文件,此文件中有一个类Ui_MainWindow(包含各种控件对象) 一、通过类继承实现: class TestMainWindow(QMainWindow, Ui_MainWindow): 定义了一个新的

    2024年04月16日
    浏览(45)
  • Pyside6(3): 自动生成UI的Qt参数输入对话框

    参数输入界面是桌面软件开发最繁琐的部分之一。特别是当系统中存在多种可编辑的数值模型时,由于各个模型的字段不同,每个字段的输入类型也不同,需要制作不同的UI,使用不同的UI控件,无疑会耗费大量时间,同时拓展性也非常差,因为每增加一个数值模型,都需要制

    2024年02月03日
    浏览(45)
  • Pyside6实现自定义widget嵌套(自定义widget为独立ui文件)

    在实际项目开发中,可能存在需要将自定义的widget嵌入到某一窗口的情况,或者为维护简洁方便,将一个大的UI文件拆分为多个独立的UI文件进行管理。这时就存在不同窗口的ui文件进行嵌套。 以widget控件为例,对实现过程进行记录,类间关系如下: 主窗口为自己编写的Main

    2024年02月08日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包