广告位联系
返回顶部
分享到

pyqt5子线程如何操作主线程GUI(示例代码)

python 来源:互联网 作者:佚名 发布时间:2024-05-19 10:18:35 人浏览
摘要

在使用pyqt5编写gui时遇到两个问题,会导致界面崩溃,今天就围绕这两个问题来简单说明和改进。 1.在主线程中使用while无限循环会导致界面崩溃 2.在子线程中操作主线程gui会导致界面崩溃 二

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

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

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

二.步骤说明

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

1)错误代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

import sys

from PyQt5.QtWidgets import  QPushButton, QTextEdit, QApplication, QHBoxLayout, QWidget

class FileChooserApp(QWidget):

    def __init__(self):

        super().__init__()

        self.initUI()

    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:

        """

        while True:

            """

            逻辑代码

            """

            self.reviewEdit.setText("测试")

if __name__ == '__main__':

    app = QApplication(sys.argv)

    ex = FileChooserApp()

    ex.show()

    sys.exit(app.exec_())

2)崩溃原因

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

3)改进方法

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

import sys

import threading

from PyQt5.QtWidgets import QPushButton, QTextEdit, QApplication, QHBoxLayout, QWidget

class FileChooserApp(QWidget):

    def __init__(self):

        super().__init__()

        self.initUI()

    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:

                """

                逻辑代码

                """

                print("123")

        send_thread = threading.Thread(target=send_a)

        # 启动线程

        send_thread.start()

if __name__ == '__main__':

    app = QApplication(sys.argv)

    ex = FileChooserApp()

    ex.show()

    sys.exit(app.exec_())

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

1)错误代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

import sys

import threading

import time

from PyQt5.QtWidgets import QPushButton, QTextEdit, QApplication, QHBoxLayout, QWidget

class FileChooserApp(QWidget):

    def __init__(self):

        super().__init__()

        self.initUI()

    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.reviewEdit.setText("设置文案")

        send_thread = threading.Thread(target=send_a)

        # 启动线程

        send_thread.start()

if __name__ == '__main__':

    app = QApplication(sys.argv)

    ex = FileChooserApp()

    ex.show()

    sys.exit(app.exec_())

2)崩溃原因

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

3)改进方法

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

1

2

3

4

class YourThread(QObject):

    show_warning_signal = pyqtSignal()

    def run(self):

        self.show_warning_signal.emit()

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

1

2

3

4

5

6

class FileChooserApp(QMainWindow):

    def __init__(self):

        super().__init__()

        self.initUI()

        self.your = YourThread()

        self.your.show_warning_signal.connect(self.settext)

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

1

2

3

4

5

6

7

8

9

10

11

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,避免出现无限循环导致应用程序冻结、响应缓慢或其他线程相关的问题

三.实例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

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_())


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计