为什么外部函数会导致PyQt5窗口冻结?

2024-09-30 20:30:31 发布

您现在位置:Python中文网/ 问答频道 /正文

下面是一些中断的示例代码: 在

import sys
import time
from PyQt5.QtWidgets import (QApplication, QDialog,
                             QProgressBar)

class Actions(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.progress = QProgressBar(self)
        self.progress.setGeometry(0, 0, 300, 25)
        self.show()

        self.count = 0

        while self.count < 100:
            self.count += 1
            time.sleep(1) # Example external function
            self.progress.setValue(self.count)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Actions()
    sys.exit(app.exec_())

运行此操作将导致它冻结并变得无响应,特别是在windows环境中。将time.sleep函数替换为任何非PyQt5函数将产生相同的结果。在

据我所知,这与函数没有在单独的线程中使用QThread调用有关。我使用this answer作为参考,并提出了一个部分解决方案。在

^{pr2}$

这将在后台运行time.sleep,并保持主窗口的响应性。但是,我不知道如何使用self.progress.setValue更新值,因为它在External类中不可访问。在

据我所知,我必须用信号来完成这个任务。大多数文档都是针对PyQt4的,这使得找到解决方案变得更加困难。在

我面临的另一个问题是能够从类Actions内启动External线程。在

这个问题的答案也将作为PyQt5的有价值的文档。 提前谢谢。在


Tags: 函数importselfactionstimeinitdefcount
2条回答

下面是一个从类Actions内部启动线程并使用按钮的版本: 在

import sys
import time

from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import (QApplication, QDialog,
                             QProgressBar, QPushButton)

class External(QThread):

    countChanged = pyqtSignal(int)

    def run(self):
        count = 0

        while count < 100:
            count += 1
            time.sleep(1)
            print(count)
            self.countChanged.emit(count)

class Actions(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.progress = QProgressBar(self)
        self.progress.setGeometry(0, 0, 300, 25)
        self.button = QPushButton('Start', self)
        self.button.move(0, 30)
        self.show()

        self.button.clicked.connect(self.onButtonClick)

    def onButtonClick(self):
        self.calc = External()
        self.calc.countChanged.connect(self.onCountChanged)
        self.calc.start()

    def onCountChanged(self, value):
        self.progress.setValue(value)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Actions()
    sys.exit(app.exec_())

必须使用信号来更新值。在

import sys
import time

from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import (QApplication, QDialog,
                             QProgressBar)

class External(QThread):
    countChanged = pyqtSignal(int)
    def run(self):
        count = 0

        while count < 100:
            count += 1
            self.countChanged.emit(count)
            print(count)
            time.sleep(1)

class Actions(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.progress = QProgressBar(self)
        self.progress.setGeometry(0, 0, 300, 25)
        self.show()

    def onCountChanged(self, value):
        self.progress.setValue(value)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Actions()
    calc = External()
    calc.countChanged.connect(window.onCountChanged)
    calc.start()
    sys.exit(app.exec_())

相关问题 更多 >