【问题标题】:setting a Qlabel text according to a variable's value on another class根据另一个类上的变量值设置 Qlabel 文本
【发布时间】:2018-02-09 17:46:39
【问题描述】:

我正在为与多个传感器交互的树莓派创建一个 GUI。我需要 GUI 来显示这些值。为此,我使用 QT 创建主窗口/UI,然后使用 pyuic5 将结果转换为 python 以在 python 上开发其他所有内容,包括实时电流图(可能在同一图上添加几条其他曲线或其他地块)。话虽这么说,我有点坚持为我一直在测试的 Qlabel 设置文本。我认为更改该文本的最佳方法是使用信号和插槽(另外我确信我将需要这些知识来处理其他事件)。

这是我运行 pyuic5 后的 UI:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1075, 622)
        self.centralWidget = QtWidgets.QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralWidget)
        self.gridLayout.setContentsMargins(11, 11, 11, 11)
        self.gridLayout.setSpacing(6)
        self.gridLayout.setObjectName("gridLayout")
        self.lblSolar = QtWidgets.QLabel(self.centralWidget)
        self.lblSolar.setObjectName("lblSolar")
        self.gridLayout.addWidget(self.lblSolar, 3, 1, 1, 1)
        self.progressBar = QtWidgets.QProgressBar(self.centralWidget)
        self.progressBar.setProperty("value", 24)
        self.progressBar.setObjectName("progressBar")
        self.gridLayout.addWidget(self.progressBar, 4, 0, 1, 1)
        self.progressBar_2 = QtWidgets.QProgressBar(self.centralWidget)
        self.progressBar_2.setProperty("value", 24)
        self.progressBar_2.setObjectName("progressBar_2")
        self.gridLayout.addWidget(self.progressBar_2, 4, 1, 1, 1)
        self.btnSelectSol = QtWidgets.QPushButton(self.centralWidget)
        self.btnSelectSol.setStyleSheet("background-color: rgb(114, 159, 207);")
        self.btnSelectSol.setObjectName("btnSelectSol")
        self.gridLayout.addWidget(self.btnSelectSol, 1, 3, 1, 1)
        self.btnSelectBat = QtWidgets.QPushButton(self.centralWidget)
        self.btnSelectBat.setStyleSheet("background-color: rgb(114, 159, 207);")
        self.btnSelectBat.setObjectName("btnSelectBat")
        self.gridLayout.addWidget(self.btnSelectBat, 2, 3, 1, 1)
        self.lblBattery = QtWidgets.QLabel(self.centralWidget)
        self.lblBattery.setObjectName("lblBattery")
        self.gridLayout.addWidget(self.lblBattery, 3, 0, 1, 1)
        self.btnON = QtWidgets.QPushButton(self.centralWidget)
        self.btnON.setObjectName("btnON")
        self.gridLayout.addWidget(self.btnON, 4, 3, 1, 1)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
        self.verticalLayout.setContentsMargins(11, 11, 11, 11)
        self.verticalLayout.setSpacing(6)
        self.verticalLayout.setObjectName("verticalLayout")
        self.lblCSTitle = QtWidgets.QLabel(self.centralWidget)
        self.lblCSTitle.setAlignment(QtCore.Qt.AlignCenter)
        self.lblCSTitle.setObjectName("lblCSTitle")
        self.verticalLayout.addWidget(self.lblCSTitle)
        self.lblCSStatus = QtWidgets.QLabel(self.centralWidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.lblCSStatus.sizePolicy().hasHeightForWidth())
        self.lblCSStatus.setSizePolicy(sizePolicy)
        self.lblCSStatus.setAutoFillBackground(False)
        self.lblCSStatus.setAlignment(QtCore.Qt.AlignCenter)
        self.lblCSStatus.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse)
        self.lblCSStatus.setObjectName("lblCSStatus")
        self.verticalLayout.addWidget(self.lblCSStatus)
        self.gridLayout.addLayout(self.verticalLayout, 0, 3, 1, 1)
        self.widget = CustomPlot(self.centralWidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth())
        self.widget.setSizePolicy(sizePolicy)
        self.widget.setObjectName("widget")
        self.gridLayout.addWidget(self.widget, 0, 0, 3, 3)
        MainWindow.setCentralWidget(self.centralWidget)
        self.menuBar = QtWidgets.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 1075, 26))
        self.menuBar.setObjectName("menuBar")
        self.menuHelp = QtWidgets.QMenu(self.menuBar)
        self.menuHelp.setObjectName("menuHelp")
        self.menuData = QtWidgets.QMenu(self.menuBar)
        self.menuData.setObjectName("menuData")
        MainWindow.setMenuBar(self.menuBar)
        self.mainToolBar = QtWidgets.QToolBar(MainWindow)
        self.mainToolBar.setObjectName("mainToolBar")
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
        self.statusBar = QtWidgets.QStatusBar(MainWindow)
        self.statusBar.setObjectName("statusBar")
        MainWindow.setStatusBar(self.statusBar)
        self.toolBar = QtWidgets.QToolBar(MainWindow)
        self.toolBar.setObjectName("toolBar")
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.actionGuide = QtWidgets.QAction(MainWindow)
        self.actionGuide.setObjectName("actionGuide")
        self.actionAbout = QtWidgets.QAction(MainWindow)
        self.actionAbout.setObjectName("actionAbout")
        self.actionExport = QtWidgets.QAction(MainWindow)
        self.actionExport.setObjectName("actionExport")
        self.menuHelp.addAction(self.actionGuide)
        self.menuHelp.addAction(self.actionAbout)
        self.menuData.addAction(self.actionExport)
        self.menuBar.addAction(self.menuHelp.menuAction())
        self.menuBar.addAction(self.menuData.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Power System Monitor"))
        self.lblSolar.setText(_translate("MainWindow", "Solar Panel"))
        self.btnSelectSol.setText(_translate("MainWindow", "Power from Solar Panel"))
        self.btnSelectBat.setText(_translate("MainWindow", "Power from Battery"))
        self.lblBattery.setText(_translate("MainWindow", "Battery"))
        self.btnON.setText(_translate("MainWindow", "EXIT"))
        self.lblCSTitle.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-size:16pt; font-weight:600;\">Pi Charge System</span></p></body></html>"))
        self.lblCSStatus.setText(_translate("MainWindow", "TextLabel"))
        self.menuHelp.setTitle(_translate("MainWindow", "Help"))
        self.menuData.setTitle(_translate("MainWindow", "Data"))
        self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
        self.actionGuide.setText(_translate("MainWindow", "Guide"))
        self.actionAbout.setText(_translate("MainWindow", "About"))
        self.actionExport.setText(_translate("MainWindow", "Export"))

from Plotter import CustomPlot

这是我的 Plotter.py 文件:

import sys
import os
os.environ['PYQTGRAPH_QT_LIB']='PyQt5'  #force pyqtgraph to use pyqt5
import pyqtgraph as pg
import PyQt5  
from pyqtgraph.Qt import QtCore, QtGui
#import numpy as np #np is used for testing plot curves
#from ina219 import INA219, DeviceRangeError #sensory library
from time import sleep
from PyQt5.QtCore import Qt, pyqtSignal
from random import randrange


#SHUNT_OHMS = 0.1
#MAX_EXPECTED_AMPS = 1.0 #2.0
#ina = INA219(SHUNT_OHMS, MAX_EXPECTED_AMPS)
#ina.configure(ina.RANGE_16V)



class  CustomPlot(pg.GraphicsWindow):
    pg.setConfigOption('background', 'w')
    pg.setConfigOption('foreground', 'k')
    ptr1 = 0
    chargeflag = "start"


    #Added a signal
    changedValue = pyqtSignal(str)


    def __init__(self, parent=None, **kargs):
        global chargeflag #variable to emit signal on change

        pg.GraphicsWindow.__init__(self, **kargs)
        #self.setParent(parent)

        p1 = self.addPlot(labels =  {'left':'Current (mA)', 'bottom':'Time(secs)'}, xRange=[0,5])
        p1.showGrid(x=True, y=True)
        p1.setYRange(3.4,4.6)
        p1.addLegend()
        #self.data1 = np.random.normal(size=10)
        #print(self.data1)
        self.data1 = []
        for n in range(10):
            #self.data1.append(ina.current()) #get actual data1 from sensor
            self.data1.append(randrange(3,5))
            sleep(1)
        #print(self.data1)
        #print(ina.current())     
        #self.data1 = ina.voltage
        #self.data2 = np.random.normal(size=10)
        self.curve1 = p1.plot(self.data1, pen='r', width=25, name='Battery')
        #self.curve2 = p1.plot(self.data2, pen=(2,3))

        timer = pg.QtCore.QTimer(self)
        timer.timeout.connect(self.update)
        #timer.timeout.connect(ina.current)
        timer.start(1000) # number of seconds (every 1000) for next update

        #setting a connection between chargeflag change and on_changed_value function
        self.chargeflag.valueChanged.connect(self.on_changed_value)

    def update(self):
        #global chargeflag
        self.data1[:-1] = self.data1[1:]  # shift data in the array one sample left (see also: np.roll)
        #self.data1[-1] = np.random.normal()
        #self.data1[-1] = ina.current() #actual value from sensor
        self.data1[-1] = randrange(3.5,4.5)

        if self.data1[-1] < 4:  #if that should send signal to update Qlabel
            self.chargeflag = "solar"            
        else:
            self.chargeflag = 'battery'

        print(self.chargeflag)

        self.ptr1 += 1
        self.curve1.setData(self.data1)
        self.curve1.setPos(self.ptr1, 0)
        #self.data2[:-1] = self.data2[1:]  # shift data in the array one sample left
                            # (see also: np.roll)
        #self.data2[-1] = np.random.normal()
        #self.curve2.setData(self.data2)
        #self.curve2.setPos(self.ptr1,0)
        self.changeflag.changedValue.connect(self.on_changed_value)


    #function for other objects from other classes to listen to                
    def on_changed_value(self, value):
        self.changedValue.emit(value)






if __name__ == '__main__':
    w = CustomPlot()
    w.show()
    QtGui.QApplication.instance().exec_()

最后是我的 main.py 文件:

import PyQt5  
from PyQt5.QtWidgets import *   
import sys 
import Powdesign
from PyQt5.QtCore import QCoreApplication, pyqtSlot
from Plotter import CustomPlot
from time import sleep


class Powapp(QMainWindow, Powdesign.Ui_MainWindow):
    def __init__(self):
        super(self.__class__, self).__init__() 
        self.setupUi(self)
        self.btnON.clicked.connect(QCoreApplication.instance().quit)
        self.lblCSStatus.setText("starting value")


    def get_chargeflag_value(self, value):
        self.lblCSStatus.setText(value)

    def make_connection(self, plot_object):
        plot_object.changedValue.connect(self.get_flag_value)

    @pyqtSlot(str)  
    def get_flag_value(self, val):
        self.lblCSStatus.setText(val)




def main():
    app = QApplication(sys.argv)  
    form = Powapp()
    form.show()
    form.make_connection(w)
    sys.exit(app.exec())          

if __name__ == '__main__':            
    main()                           

对于我的信号和插槽实现,我基于以下示例:https://blog.manash.me/quick-pyqt5-1-signal-and-slot-example-in-pyqt5-bf502ccaf11d

我在 Plotter.py 上创建了变量 changeflag,它将根据传感器的值从“太阳能”变为“电池”,这是我想在 Qlabel 上显示的文本,但我很漂亮当然那是我的错。我想我应该创建某种会发出信号的 Qobject,但我不清楚这是否允许或如何去做。提前非常感谢!

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 pyqtgraph


    【解决方案1】:

    您的代码中有几个错误:

    1. 变量chargeflag是一个字符串,没有valueChanged方法。

    2. valueChanged 是 CustomPlot 类的一个属性,如果你在类中使用它,你应该使用 self 实例:self.changedValue.emit(some_string)

    3. 这不是错误,但我认为没有必要,您不需要创建插槽来发出信号,您可以在课堂上的任何地方进行。

    4. 没有必要创建一个make_connection方法,除了你传递从未创建过的w,使用Qt Designer时,它成为类的成员:self.widget = CustomPlot(self.centralWidget),所以你可以将它连接到Powapp 类:self.widget.changedValue.connect(self.get_flag_value)

    以上所有都在下一个类中实现,我修改了代码的其他部分但它们并不重要,除了randrange()函数需要整数和非浮点值作为输入,所以我改变了@ 987654326@ 函数来自同一随机模块的uniform(),因此它将导入:from random import randrange 更改为from random import uniform

    Plotter.py

    class  CustomPlot(pg.GraphicsWindow):
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        ptr1 = 0
        #Added a signal
        changedValue = pyqtSignal(str)
    
        def __init__(self, parent=None, **kargs):
            pg.GraphicsWindow.__init__(self, **kargs)
            #self.setParent(parent)
    
            p1 = self.addPlot(labels =  {'left':'Current (mA)', 'bottom':'Time(secs)'}, xRange=[0,5])
            p1.showGrid(x=True, y=True)
            p1.setYRange(3.4,4.6)
            p1.addLegend()
            #self.data1 = np.random.normal(size=10)
            #print(self.data1)
            self.data1 = [uniform(3,5) for _ in range(10)]
            # self.data1 = [ina.current() for _ in range(10)] 
            #print(self.data1)
            #print(ina.current())     
            #self.data1 = ina.voltage
            #self.data2 = np.random.normal(size=10)
            self.curve1 = p1.plot(self.data1, pen='r', width=25, name='Battery')
            #self.curve2 = p1.plot(self.data2, pen=(2,3))
    
            timer = pg.QtCore.QTimer(self)
            timer.timeout.connect(self.update)
            #timer.timeout.connect(ina.current)
            timer.start(1000) # number of seconds (every 1000) for next update
    
            #setting a connection between chargeflag change and on_changed_value function
    
        def update(self):
            #global chargeflag
            self.data1[:-1] = self.data1[1:]  # shift data in the array one sample left (see also: np.roll)
            #self.data1[-1] = np.random.normal()
            #self.data1[-1] = ina.current() #actual value from sensor
            self.data1[-1] = uniform(3.5,4.5)
    
            chargeflag = "solar" if self.data1[-1] < 4 else "battery"
    
            self.ptr1 += 1
            self.curve1.setData(self.data1)
            self.curve1.setPos(self.ptr1, 0)
            #self.data2[:-1] = self.data2[1:]  # shift data in the array one sample left
                                # (see also: np.roll)
            #self.data2[-1] = np.random.normal()
            #self.curve2.setData(self.data2)
            #self.curve2.setPos(self.ptr1,0)
            self.changedValue.emit(chargeflag)
    
    
    if __name__ == '__main__':
        w = CustomPlot()
        w.show()
        QtGui.QApplication.instance().exec_()
    

    ma​​in.py

    class Powapp(QMainWindow, Ui_MainWindow):
        def __init__(self):
            super(self.__class__, self).__init__() 
            self.setupUi(self)
            self.btnON.clicked.connect(QCoreApplication.instance().quit)
            self.lblCSStatus.setText("starting value")
            self.widget.changedValue.connect(self.get_flag_value)
    
    
        def get_chargeflag_value(self, value):
            self.lblCSStatus.setText(value)
    
        @pyqtSlot(str)  
        def get_flag_value(self, val):
            self.lblCSStatus.setText(val)
    
    def main():
        app = QApplication(sys.argv)  
        form = Powapp()
        form.show()
        sys.exit(app.exec_())          
    
    if __name__ == '__main__':            
        main()  
    

    【讨论】:

    • 非常感谢我的朋友,它就像一个魅力!我还将您的代码与我的代码进行了比较,并理解了我的所有错误。我只是有一个疑问,在您第一次更正时,valueChanged 方法仅用于 Qobjects 吗?现在我将继续向 GUI 添加自定义小部件。我将尝试实现一个模拟仪表,就像您在湿度计示例中使用的仪表一样。再次感谢您的帮助!
    • 只有从它派生的对象或类才能发出信号,而Widgets继承自QObjects,所以你也可以使用它。
    猜你喜欢
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 2014-10-06
    • 2010-12-01
    • 2023-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多