2017-08-31 16 views
1

私はいくつかのセンサーと相互作用するラズベリーパイのGUIを作成しています。これらの値を表示するにはGUIが必要です。このためにQTを使ってメインウィンドウ/ UIを作成し、その結果をpyuic5を使ってPythonに変換して、Pythonで他のものを開発しました。リアルタイムのプロットも含まれています(同じプロットまたは付加的なプロット)。それは、私がテストしてきたQlabelのテキストを設定することに固執していると言われています。私は、そのテキストを変更するための最良の方法は、信号とスロット(と私は他のイベントの知識を必要としていると確信している)となると思う。ここで別のクラスの変数の値に応じてQlabelテキストを設定する

はpyuic5を実行した後、私のUIである:

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

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ファイルですシグナルとスロットの実装私は次の例に基づいていました:https://blog.manash.me/quick-pyqt5-1-signal-and-slot-example-in-pyqt5-bf502ccaf11d

私はQlabelに表示したいテキストであるセンサの値に応じて、 "solar"から "battery"に変化するPlotter.pyに変数changeflagを作成しましたが、私はかなりです確かにそれは私の間違いです。私はシグナルを放出する何らかのQobjectを作成することになっていると思いますが、それが許されているか、それをどうやって行うのかは明らかではありません。ありがとうございます!

答えて

1

あなたのコード内のいくつかのエラーがあります

  1. は、変数chargeflagは文字列であり、一切のvalueChanged方法を持っていません。

  2. のvalueChangedはCustomPlotクラスの属性であり、あなたがクラス内にそれを使用している場合は、selfインスタンスを使用してそれを行う必要があります:self.changedValue.emit(some_string)

  3. これはエラーではありませんが、私はそれが必要ではないと思います、シグナルを放射するためのスロットを作成する必要はありません。クラス内のどこでも実行できます。

  4. Qtデザイナを使用しているときに、あなたが渡したw以外にmake_connectionメソッドを作成する必要はありません。これはクラスのメンバーになります:self.widget = CustomPlot(self.centralWidget)、Powappクラス:self.widget.changedValue.connect(self.get_flag_value)

上記の次のクラスで実装されている、私はあなたのコードの他の部分を変更したが、それらはほとんど重要であり、randrange()関数は、入力として整数と非浮動値が必要に加えて、私は変更のすべて同じランダムモジュールからuniform()によってrandrange()機能は、それがインポートを変更:from random import randrange

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_() 
Plotter.py

from random import uniform

main。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() 
+0

私の友人に感謝します。それは魅力的です!私はあなたのコードをもう一度比較して、すべてのエラーを理解しました。あなたの最初の修正で、valueChangedメソッドが単にQobjectsで使用されることに疑問がありますか?今度はGUIにカスタムウィジェットを追加していきます。私は、湿度計の例で使用したようなアナログゲージを実装しようとします。もう一度、あなたの助けをありがとう! –

+0

それから派生したオブジェクトやクラスだけがシグナルを出すことができ、ウィジェットはQObjectsを継承します。 – eyllanesc

関連する問題