根据发出的信号更新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;dr

问题是您调用了setupUi两次,第二次它使用另一个小部件作为参数。

为什么它不起作用

当您使用pyuic生成文件时,它实际上会基于Python的object类型创建一个类。该类本身不做任何事情,只是一个以"Python方式"加载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 thebaseclass
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)

现在uiwindow实例的一个属性;让我们再次"翻译"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继承了的方法和属性QwidgetUi_Form。让我们再翻译一遍(注意课堂(:

class MyWidget(object):
def setupUi(window,window):
window.setObjectName("Form")
window.progressBar = QtWidgets.QProgressBar(window)

这种方法使所有小部件都成为实例的直接属性(self.progressBar等(,我通常建议这样做,因为它更直接、更简单(经常发生的情况是,您试图访问一个小部件,却忘记了ui前缀,使用这种方法不会发生这种情况(。


现在,终于是你的问题了

window = QWidget()
app = MyTest()

在MyTest的__init__中调用setupUi,这意味着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

最新更新