pyqt5 子线程如何操作主线程GUI

一.简介

在使用pyqt5编写gui时遇到两个问题,会导致界面崩溃,今天就围绕这两个问题来简单说明和改进。

1.在主线程中使用while无限循环会导致界面崩溃

2.在子线程中操作主线程gui会导致界面崩溃

二.步骤说明

1.在主线程中使用while无限循环会导致界面崩溃

1)错误代码

 View Code

2)崩溃原因

我们先来说下while崩溃的问题,这边我设置的循环是一个无限循环,不会给 GUI 事件循环任何运行的机会。在 PyQt 或其他 GUI 框架中,GUI 的事件循环(例如按钮点击、窗口移动等)必须在单独的线程中运行,以保持 GUI 的响应性

3)改进方法

将循环体在一个子线程中执行,就可以避免这个问题,代码如下。

 View Code

2.在子线程中操作主线程gui会导致界面崩溃

1)错误代码

 View Code

2)崩溃原因

上述中试图在子线程send_a方法中给文本编辑器设置文案。这是不允许的,因为 PyQt 和大多数 GUI 框架一样,要求所有的 GUI 更新必须在主线程(也称为 GUI 线程)中执行。

3)改进方法

既然在子线程中无法操作主线程gui更新,那么只能在主线程中去执行,这就需要信号与槽的配合了。我们先来自定义一个信号

class YourThread(QObject):
    show_warning_signal = pyqtSignal()

    def run(self):
        self.show_warning_signal.emit()

在初始化的时候去实例化YourThread类,连线信号与槽

class FileChooserApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.your = YourThread()
        self.your.show_warning_signal.connect(self.settext)

接着在子线程中直接去触发信号即可

    def send(self):
        def send_a():
            while True:
                """
                循环体
                """
                self.your.run()
                time.sleep(2)

        send_thread = threading.Thread(target=send_a)
        # 启动线程
        send_thread.start()

执行每次循环需要等待2s,避免出现无限循环导致应用程序冻结、响应缓慢或其他线程相关的问题

三.实例

import sys
import threading
import time

from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtWidgets import QPushButton, QTextEdit, QApplication, QHBoxLayout, QWidget


class YourThread(QObject):
    show_warning_signal = pyqtSignal()

    def run(self):
        self.show_warning_signal.emit()


class FileChooserApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.your = YourThread()
        self.your.show_warning_signal.connect(self.settext)

    def initUI(self):
        button = QPushButton("按钮")

        self.reviewEdit = QTextEdit()
        self.reviewEdit.move(100, 100)

        button.clicked.connect(self.send)

        hbox1 = QHBoxLayout()  # 创建一个水平布局
        hbox1.addWidget(button)  # 添加按钮到水平布局中
        hbox1.addStretch(1)  # 设置水平比例间距
        hbox1.addWidget(self.reviewEdit)  # 添加按钮到水平布局中

        self.setLayout(hbox1)  # 添加到布局器
        self.setWindowTitle('文件选择器')
        self.setGeometry(300, 300, 500, 500)

    def send(self):
        """
        事件
        :return:
        """

        def send_a():
            while True:
                """
                逻辑代码
                """
                self.your.run()
                time.sleep(2)

        send_thread = threading.Thread(target=send_a)
        # 启动线程
        send_thread.start()

    def settext(self):
        self.reviewEdit.setText("123")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = FileChooserApp()
    ex.show()
    sys.exit(app.exec_())

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值