尝试从外部脚本更新进度条时,QWidget 变得无响应[重复]
Posted
技术标签:
【中文标题】尝试从外部脚本更新进度条时,QWidget 变得无响应[重复]【英文标题】:QWidget becomes unresponsive when trying to update progressbar from external script [duplicate] 【发布时间】:2019-07-30 16:05:58 【问题描述】:我正在尝试学习如何在我的 for 循环在外部脚本中运行时更新我的主脚本中的进度条。这是我第一次尝试使用信号,所以我不确定我是否正确使用了它们。这是我到目前为止所尝试的。
我尝试做的第一件事是创建一个类“Signal”,它具有跟踪进度条的 pyqtSignal。然后我创建了一个信号对象,并让它在每次 for 循环运行时发出一个信号。然后在我的主脚本中,我尝试将我创建的信号对象连接到进度条的 setValue 方法。进度条更新到 5%,然后窗口变得无响应。关于代码,我有两个主要问题:
窗口无响应的原因是什么?
如何让主脚本中的进度条更新以使窗口不会变得无响应?
main.py
import sys
from external import *
from PyQt5.QtWidgets import QWidget, QApplication, QProgressBar,
QPushButton, QVBoxLayout
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Testing')
self.setGeometry(300, 300, 290, 150)
self.vbox = QVBoxLayout()
self.setLayout(self.vbox)
self.progressbar = QProgressBar(self)
self.button = QPushButton("run", self)
self.vbox.addWidget(self.progressbar)
self.vbox.addWidget(self.button)
c.update.connect(self.progressbar.setValue)
self.button.clicked.connect(test)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
external.py
from PyQt5.QtCore import pyqtSignal, QObject
import time
class Signal(QObject):
update = pyqtSignal(int)
c = Signal()
def test():
for i in range(100):
c.update.emit(i)
time.sleep(1)
【问题讨论】:
【参考方案1】:即使 for 循环代码在另一个文件中也没关系,因为它是在 PyQt QApplication 事件循环(以app.exec_()
开头的那个)内执行的。time.sleep
会阻止一切直到完成,包括 GUI,这就是界面变得无响应的原因。
您需要在单独的线程中运行循环函数。 这是一个非常基本的解决方案:
import threading
[...]
def initUI(self):
[...]
c.update.connect(self.updateProgressBar)
self.button.clicked.connect(self.runTest)
self.show()
def runTest(self):
threading.Thread(target=test).start()
self.button.setEnabled(False)
def updateProgressBar(self, value):
self.progressbar.setValue(value)
if value == 100:
self.button.setEnabled(True)
注意:我已将 test
函数的范围设置为 101,因此当它达到 100 时,它会再次启用该按钮,因为我已禁用它以避免多次并发执行该函数。
也就是说,我不建议您采用这种方法,因为它肯定会在未来产生问题。 查看this 的答案,它可能会让您了解更好的(和建议的)线程方法。
【讨论】:
以上是关于尝试从外部脚本更新进度条时,QWidget 变得无响应[重复]的主要内容,如果未能解决你的问题,请参考以下文章
从 powershell 下载文件时,Invoke-WebRequest 进度变得无响应/暂停
如何将 QWidget 类中的 lineedit 字符串共享到工作线程