从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)
现在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()
在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
。