обновить значение progressBar из излучаемого сигнала - PullRequest
0 голосов
/ 18 марта 2020

получает процент загрузки процессора из psutil и отображает его на индикаторе выполнения. Мне удалось отобразить значение процента процессора, но он не обновляется. у меня есть файл от дизайнера QT с именем Progress, я конвертирую его с помощью pyuic5 в файл py и импортирую его в основной файл с именем cpuprogress.py, а также я создал файл python с именем sysinfo, чтобы получить значение процента процессора и импортировать его в основной файл.

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_())

введите описание изображения здесь

1 Ответ

0 голосов
/ 18 марта 2020

tl; dr

Проблема в том, что вы дважды вызывали setupUi, а второй раз он использовал другой виджет в качестве аргумента.

Почему это не работает?

Когда вы генерируете файл с pyui c, он фактически создает класс на основе типа Python object. Этот класс ничего не делает сам по себе, это просто «интерфейс» для загрузки элементов пользовательского интерфейса «pythoni c way».

Если вы попытаетесь открыть один из этих файлов (который Если никогда нельзя редактировать!), вы увидите что-то вроде этого:

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 <i>base</i> 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 и его аргумент, затем go назад к содержимому файла, созданного с помощью pyui c:

    def setupUi(self, Form):
        Form.setObjectName("Form")
        self.progressBar = QtWidgets.QProgressBar(Form)

Form - это экземпляр QWidget, созданный ранее ("окно"), тогда как, очевидно, self относится к экземпляру Ui_Form; давайте переведем переменные в имя экземпляров, которые они представляют:

    def setupUi(<b>ui</b>, <b>window</b>):
        <b>window</b>.setObjectName("Form")
        <b>ui</b>.progressBar = QtWidgets.QProgressBar(<b>window</b>)

В примере в начале это означает, что, хотя window отображается с дочерними виджетами, они не атрибуты экземпляра: нет window.progressBar.

Во втором примере в документации показан метод «одиночного наследования», который позволяет реализовать взаимодействия между виджетами («logi c») , Я буду использовать имена классов, как и выше:

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(<b>window.ui</b>, <b>window</b>):
        <b>window</b>.setObjectName("Form")
        <b>window.ui</b>.progressBar = QtWidgets.QProgressBar(<b>window</b>)

Это означает, что теперь вы можете иметь доступ к виджетам из экземпляра окна. , но только через 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(<b>window</b>, <b>window</b>):
        <b>window</b>.setObjectName("Form")
        <b>window</b>.progressBar = QtWidgets.QProgressBar(<b>window</b>)

Этот подход делает все виджеты прямыми атрибутами экземпляра (self.progressBar, et c), и я обычно предлагаю это как более прямой и просто (часто случается так, что вы пытаетесь получить доступ к виджету и забываете префикс ui, с этим методом этого не происходит).


Теперь, наконец, ваша проблема.

window = QWidget()
app = MyTest()

setupUi вызывается в __init__ MyTest, что означает, что app имеет атрибут с именем progressBar, который в этот момент должен быть "видимым", как только мы вызовем app.show() .
Вы также создали другой виджет (window) и использовали setupUi, используя , что в качестве параметра:

app.setupUi(window)

Давайте переведем его в последний раз (для чтобы избежать путаницы, давайте изменим имя «оконного» QWidget, который вы создали по ошибке):

    def setupUi(<b>app</b>, <b>otherWindow</b>):
        <b>otherWindow</b>.setObjectName("Form")
        <b>app</b>.progressBar = QtWidgets.QProgressBar(<b>otherWindow</b>)

Как вы можете видеть, теперь вы «перезаписали» атрибут app.progressBar, но этот индикатор выполнения на самом деле новый один, и это ребенок window (который вы никогда не показываете).

Функция updateProgressBar затем успешно изменит значение индикатора выполнения, но не того, который вы видите.

Наконец, есть и другой способ использования файлов пользовательского интерфейса, и это через модуль uic, который может напрямую загружать файлы пользовательского интерфейса.

from PyQt5 import QtWidgets, uic

class MyTest(QtWidgets.QWidget):
    def __init__(self, parent=None)
        super().__init__(parent)
        <b>uic.loadUi('mywindow.ui', self)</b>

Этот подход является большим преимуществом с другой стороны: вам больше не нужно создавать файлы с pyui c, и он ведет себя точно так же, как метод множественного наследования, поэтому вы можете использовать self.progressBar, как и раньше.

...