【问题标题】:Pyqt5 GUI Still Hangs When Using Thread使用线程时 Pyqt5 GUI 仍然挂起
【发布时间】:2016-05-10 06:39:57
【问题描述】:

我是 python 和 pyqt 的新手。 我正在学习如何在 GUI 中使用线程。

我按照这个教程 http://www.xyzlang.com/python/PyQT5/pyqt_multithreading.html

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
import threading
from _ast import While

class Communicate(QObject):
    signal = pyqtSignal(int, str)

class My_Gui(QWidget):
    def __init__(self):
        super().__init__()

        self.comm = Communicate()
        self.comm.signal.connect(self.append_data)
        self.initUI()

    def initUI(self):

        btn_count = QPushButton('Count')
        btn_count.clicked.connect(self.start_counting)
        self.te = QTextEdit()

        vbox = QVBoxLayout()
        vbox.addWidget(btn_count)
        vbox.addWidget(self.te)

        self.setLayout(vbox)
        self.setWindowTitle('MultiThreading in PyQT5')
        self.setGeometry(400, 400, 400, 400)
        self.show()

    def count(self, comm):
        '''
        for i in range(10):
            data = "Data "+str(i)
            comm.signal.emit(i, data)
        '''
        i = 0
        while True:
            data = "Data "+str(i)
            comm.signal.emit(i, data)
            i+=1

    def start_counting(self):
        my_Thread = threading.Thread(target=self.count, args=(self.comm,))
        my_Thread.start()

    def append_data(self, num, data):
        self.te.append(str(num) + " " + data)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    my_gui = My_Gui()
    sys.exit(app.exec_())

我将 for 循环更改为无限 while 循环(递增 'i')。

如果我执行程序,GUI 仍然会挂起,但如果我删除循环内的发出信号,它就不再挂起。

有没有什么技巧可以让它不挂起?

【问题讨论】:

  • 请解释我的问题有什么问题,而不是投反对票。是不是因为我的问题太基础了?

标签: python python-3.x pyqt pyqt5


【解决方案1】:

while True 在后台无限循环

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
import threading
from _ast import While

class Communicate(QObject):
    signal = pyqtSignal(int, str)

class My_Gui(QWidget):
    def __init__(self):
        super().__init__()

        self.comm = Communicate()
        self.comm.signal.connect(self.append_data)
        self.initUI()

    def initUI(self):

        btn_count = QPushButton('Count')
        btn_count.clicked.connect(self.start_counting)
        self.te = QTextEdit()

        vbox = QVBoxLayout()
        vbox.addWidget(btn_count)
        vbox.addWidget(self.te)

        self.setLayout(vbox)
        self.setWindowTitle('MultiThreading in PyQT5')
        self.setGeometry(400, 400, 400, 400)
        self.show()

    def count(self, comm):
        for i in range(10):
            data = "Data "+str(i)
            comm.signal.emit(i, data)
        # While True below will never stop and cause your program to stuck
        '''
        i = 0
        while True:
            data = "Data "+str(i)
            comm.signal.emit(i, data)
            i+=1
        '''

    def start_counting(self):
        my_Thread = threading.Thread(target=self.count, args=(self.comm,))
        my_Thread.start()

    def append_data(self, num, data):
        self.te.append(str(num) + " " + data)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    my_gui = My_Gui()
    sys.exit(app.exec_())

【讨论】:

    【解决方案2】:

    我认为你在两件事上被否决了:

    1. 您只是复制并粘贴了教程中的代码
    2. 您没有阅读教程

    在教程中,作者指出:

    在上面的例子中,我们创建了一个 QPushbutton 和 QTextEdit。单击按钮时,它会创建一个从 0 到 9 计数的新线程并发出信号,以便在 QTextEdit 中附加数字和数据。在类 Communicate 中,信号被初始化为 pyqtSignal(int, str)。这个 int 和 str 意味着当一个信号将被发出时,它还将传递两个参数,第一个参数是 Integer 类型,第二个参数是 String 类型。

    通过将循环更改为while true,您可以连续发出信号并将文本附加到 QTextEdit 中。可能不是你想要的。 同样在内部注释emit 语句会继续运行while 循环。

    【讨论】:

    • 嗨,我阅读了教程并且已经理解,但我不知道它为什么会挂起。我没有复制所有代码,我修改了循环代码。在Java中,您可以使用invokeLater从后台线程更新UI,我认为'emit'在python中是等价的。在Java中使用相同的逻辑来测试线程,我只想知道它为什么会在python中挂起。 “发射”有什么限制吗?还是例子错了?这就是我问的原因。
    • 更新 GUI 对于 Java 和 Python/PyQt 的工作方式不同。请看这里:link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 2011-11-22
    • 2018-11-08
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    相关资源
    最近更新 更多