python - 从发出的信号更新 progressBar 值
问题描述
从 psutil 获取 CPU 百分比并将其显示在进度条上。我能够显示 CPU 百分比的值,但它没有更新。我有一个来自 QT 设计器的名为 Progress 的文件我使用 pyuic5 将其转换为 py 文件并将其导入名为 cpuprogress.py 的主文件中,我还创建了一个名为 sysinfo 的 python 文件以获取 CPU 百分比的值并将其导入主文件文件。
import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import (QWidget, QApplication)
from progress import Ui_Form
import sysinfo
class MyTest(QWidget, Ui_Form):
def __init__(self, parent = None):
super(MyTest, self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadCLass()
self.threadclass.start()
self.threadclass.change_value.connect(self.updateProgressBar)
def updateProgressBar(self, val):
self.progressBar.setValue(val)
class ThreadCLass(QThread):
change_value = pyqtSignal(int)
def __init__(self, parent = None):
super(ThreadCLass, self).__init__(parent)
def run(self):
while 1:
val = int(sysinfo.getCPU())
self.change_value.emit(val)
a =QApplication(sys.argv)
window = QWidget()
app = MyTest()
app.setupUi(window)
app.show()
sys.exit(a.exec_())
解决方案
tl;博士
问题是您调用setupUi
了两次,第二次使用另一个小部件作为参数。
为什么它不起作用?
当您使用 pyuic 生成文件时,它实际上会根据 Python 的object
类型创建一个类。该类本身不做任何事情,只是一个以“pythonic方式”加载ui元素的“接口”。
如果您尝试打开其中一个文件(永远不应编辑!),您将看到如下内容:
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
self.progressBar = QtWidgets.QProgressBar(Form)
self.progressBar.setProperty("value", 24)
# ...
def retranslateUi(self, Form):
# things related to the localization of the ui
使用 Designer报告的官方指南作为第一个示例,除了显示窗口之外实际上什么都不做。
from PyQt5.QtWidgets import QApplication, QWidget
from ui_form import Ui_Form
# create an instance of the base class
window = QWidget()
# create an instance of the Ui "builder"
ui = Ui_Form()
# apply the ui to the base class created before
ui.setupUi(window)
最后一步是最重要的理解:仔细查看该setupUi
方法属于什么对象,以及它的参数,然后回到使用 pyuic 创建的文件的内容:
def setupUi(self, Form):
Form.setObjectName("Form")
self.progressBar = QtWidgets.QProgressBar(Form)
Form
是之前创建的QWidget实例(“window”),而显然self
是指的实例Ui_Form
;让我们用它们所代表的实例的名称来翻译变量:
def setupUi(ui, window):
window.setObjectName("Form")
ui.progressBar = QtWidgets.QProgressBar(window)
在开头的示例中,这意味着,虽然window
与它的子小部件一起显示,但它们不是实例的属性:没有window.progressBar
.
文档中的第二个示例显示了“单一继承”方法,该方法允许实现小部件之间的交互(“逻辑”)。我将像上面一样使用类名:
from PyQt5.QtWidgets import QApplication, QWidget
from ui_form import Ui_Form
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
现在ui
是window
实例的一个属性;让我们再次“翻译” setupUi
,假设现在“self”是正在创建的 MyWidget 的实例:
class Ui_Form(object):
def setupUi(window.ui, window):
window.setObjectName("Form")
window.ui.progressBar = QtWidgets.QProgressBar(window)
这意味着现在您可以从窗口实例访问小部件,但只能通过self.ui
(如window.ui)。
现在,让我们看看多重继承方法,它非常相似:
class MyWidget(QWidget, Ui_Form):
def __init__(self):
super(MyWidget, self).__init__()
self.setupUi(self)
在这种情况下,MyWidget 继承自 Qwidget 和 Ui_Form 的方法和属性。让我们再翻译一遍(注意类):
class MyWidget(object):
def setupUi(window, window):
window.setObjectName("Form")
window.progressBar = QtWidgets.QProgressBar(window)
这种方法使所有小部件成为实例的直接属性(self.progressBar
等),我通常建议它,因为它更直接和简单(经常发生您尝试访问小部件并忘记该ui
前缀,使用这种方法它不会发生)。
现在,最后,你的问题。
window = QWidget()
app = MyTest()
setupUi
在 MyTest 中被调用__init__
,这意味着它app
有一个名为 的属性progressBar
,此时它应该是“可见”的,只要我们调用app.show()
.
您还创建了另一个小部件(window
),并将setupUi
其用作参数:
app.setupUi(window)
让我们最后一次翻译它(为避免混淆,让我们更改您错误创建的“窗口”QWidget的名称):
def setupUi(app, otherWindow):
otherWindow.setObjectName("Form")
app.progressBar = QtWidgets.QProgressBar(otherWindow)
如您所见,现在您已经“覆盖”了该app.progressBar
属性,但该进度条实际上是一个新进度条,并且它是子项window
(您从未显示)。
然后 updateProgressBar 函数将成功修改进度条的值,但不是您看到的那个。
最后,还有另外一种使用ui文件的方式,就是通过uic
模块,可以直接加载ui文件。
from PyQt5 import QtWidgets, uic
class MyTest(QtWidgets.QWidget):
def __init__(self, parent=None)
super().__init__(parent)
uic.loadUi('mywindow.ui', self)
这种方法的另一大优势是:您不必再使用 pyuic 创建文件,它的行为与多重继承方法完全相同,因此您可以self.progressBar
像以前一样使用。
推荐阅读
- c++ - 进程以 -1073741571 状态终止(0 分钟,3 秒)
- python - tf.convert_to_tensor(pred_labels) - ValueError: Argument must be a dense tensor: got shape [2, 436, 1024, 2],但想要 [2]
- python - Python collections.Mapping:__iter__ 和 __contains__ 尚未提供的 dict_keys 的使用
- c# - 如何在 Visual Studio 中以特定方向加载图像?
- python - 使用触摸事件获取小部件中图像的像素坐标
- javascript - 为什么这个反向堆栈函数返回未定义而不是预期的输出?
- reactjs - 为什么 React-Table 列数组对象既有 camelCasing 又有 PascalCasing
- android - 如何为流星科尔多瓦应用程序建立深层链接?
- kdb - 有没有办法将stdout作为q中的字符串重定向到变量,或者以其他方式对变量进行字符串化?
- vba - DoCmd.OpenForm 编译错误,“预期:=”