尝试使用 PyQt5 获取 GUI 的实时绘图 [英] Trying get a live plot for a GUI with PyQt5

查看:67
本文介绍了尝试使用 PyQt5 获取 GUI 的实时绘图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在通过阅读和提问,我已经可以在 LCD 上显示数值,但现在想制作图表.

Right now through reading and asking questions I have gotten to a point where I can display the numerical values on LCDs, but now would like to make a graph.

在下面的图片中有一张图片,我将把它作为图表的背景.对于 Dyno,收集的重要信息是扭矩和马力.这些我是用我的 Python 3.5 代码计算的,数据是使用 arduino 收集的.

In the Picture below there is a picture that I am going to have as a backdrop for the graph. For a Dyno the important information that is gathered is Torque and HorsePower. These I have being calculated with my Python 3.5 Code and the data is being gathered by using an arduino.

对于我的图表,我实际上想在数据输入的同时绘制两条线.我想同时绘制扭矩和马力.这两者都与使用 Dyno 的时间有关.然而,这可能很难,因为它们需要用不同的 y 轴绘制.根据我一直在阅读的内容,使用 pyqtGraph 是这项工作的最佳选择,但由于我在此类工作方面的经验,我真的不知道该怎么做.

For my graph I actually want to plot two lines at the same time as the data comes in. I would like to plot both the Torque and the HorsePower at the same time. Both of those vs the time that the Dyno is being used. This however might be hard since they need to be plotted with different y-axis. From what I have been reading using pyqtGraph is the best option for the job but due to my in experience with this kind of work I really don't know how to do it.

下面是我根据我发现的一些东西尝试运行的代码.运行它不会出错我的代码,但是它也不会与图形区域交互.我试图让它以与 LCD 类似的方式工作,但即使如此我仍然没有任何工作.

Below is my code that I have tried to run based on some of the things I have found. Running it does not error out my code, however It also does not interact with the graph area. I tried to get it to work in a similar fashion that the LCDs work in, but even still I don't have anything working.

"""
SCSU DYNO GUI PROGRAM

created 10/20/2017
"""


import sys
import time
import csv
import numpy as np
import warnings
import serial
import serial.tools.list_ports
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread,QTimer, pyqtSignal
from PyQt5.QtWidgets import QMessageBox,QWidget, QApplication
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import random
from DynoTest1 import Ui_DynoTest1


__author__ = 'Matt Munn'

class GetData(QThread):
    dataChanged = pyqtSignal(float, float, float, float, float, float, float, float)

    #Distance = 0.5 #This is dependent on the lever arm.

    def __init__(self, parent=None):
        QThread.__init__(self, parent)

        arduino_ports = [  # automatically searches for an Arduino and selects the port it's on
            p.device
            for p in serial.tools.list_ports.comports()
            if 'Arduino' in p.description
        ]

        if not arduino_ports:
            raise IOError("No Arduino found - is it plugged in? If so, restart computer.")
        if len(arduino_ports) > 1:
            warnings.warn('Multiple Arduinos found - using the first')
        self.Arduino = serial.Serial(arduino_ports[0], 9600, timeout=1)

    def __del__(self):  # part of the standard format of a QThread
        self.wait()

    def run(self):  # also a required QThread function, the working part
        self.Arduino.close()
        self.Arduino.open()

        self.Arduino.flush()
        self.Arduino.reset_input_buffer()
        start_time = time.time()

        Distance = 0.5 #This is dependent on the lever arm.
        Max_RPM = 0
        Max_HorsePower = 0
        Max_Torque = 0

        while True:
            while self.Arduino.inWaiting() == 0:
                pass
            try:
                data = self.Arduino.readline()
                dataarray = data.decode().rstrip().split(',')
                self.Arduino.reset_input_buffer()
                Force = round(float(dataarray[0]), 3)
                RPM = round(float(dataarray[1]), 3)
                if Max_RPM < RPM:
                    Max_RPM = RPM
                Torque = round(Force * Distance, 3)
                if Max_Torque < Torque:
                    Max_Torque = Torque
                HorsePower = round(Torque * RPM / 5252, 3)
                if Max_HorsePower < HorsePower:
                    Max_HorsePower = HorsePower
                Run_Time = round(time.time() - start_time, 3)
                print(Force, 'Grams', ",", RPM, 'RPMs', ",", Torque, "ft-lbs", ",", HorsePower, "hp", Run_Time,
                      "Time Elasped")
                self.dataChanged.emit(Force, RPM, Max_RPM, Torque, Max_Torque, HorsePower, Max_HorsePower, Run_Time)
            except (KeyboardInterrupt, SystemExit, IndexError, ValueError):
                pass
class GUI(QWidget, Ui_DynoTest1):


    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setupUi(self)
        self.thread = GetData(self)
        self.thread.dataChanged.connect(self.onDataChanged)
        self.thread.start()
    """
        layout = QtGui.QHBoxLayout()
        self.plot = pg.PlotWidget()
        layout.addWidget(self.plot)
        self.setLayout(layout)

    def plotter(self):

        self.data = [0]
        self.curve = self.plot.getPlotItem().plot()
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updater)
        self.timer.start(0)

    def updater(self):
        self.data.append(self.data[-1]+0.2*(0.5-random.random()))
        self.curve.setData(self.data)
    """
    def onDataChanged(self, Force, RPM, Max_RPM, Torque,Max_Torque, HorsePower, Max_HorsePower, Run_Time):
        self.lcdNumber.display(Max_RPM)
        self.lcdNumber_2.display(Max_Torque)
        self.lcdNumber_3.display(Max_HorsePower)
        self.lcdNumber_4.display(RPM)
        self.lcdNumber_5.display(Torque)
        self.lcdNumber_6.display(HorsePower)
        self.lcdNumber_7.display(Run_Time)
        #self.graphicsView.display(Tourque,Run_Time)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    Dyno = GUI()
    Dyno.show()
    sys.exit(app.exec_())

这是QTDesigner生成的代码.

This is the code generated by the QTDesigner.

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'dynotest1.ui'
#
# Created by: PyQt5 UI code generator 5.9
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_DynoTest1(object):
    def setupUi(self, DynoTest1):
        DynoTest1.setObjectName("DynoTest1")
        DynoTest1.resize(1001, 695)
        self.verticalLayout_4 = QtWidgets.QVBoxLayout(DynoTest1)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout()
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.pushButton_2 = QtWidgets.QPushButton(DynoTest1)
        self.pushButton_2.setObjectName("pushButton_2")
        self.gridLayout.addWidget(self.pushButton_2, 1, 0, 1, 1)
        self.pushButton_4 = QtWidgets.QPushButton(DynoTest1)
        self.pushButton_4.setObjectName("pushButton_4")
        self.gridLayout.addWidget(self.pushButton_4, 1, 1, 1, 1)
        self.pushButton_3 = QtWidgets.QPushButton(DynoTest1)
        self.pushButton_3.setObjectName("pushButton_3")
        self.gridLayout.addWidget(self.pushButton_3, 0, 1, 1, 1)
        self.pushButton = QtWidgets.QPushButton(DynoTest1)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
        self.verticalLayout_3.addLayout(self.gridLayout)
        self.label_3 = QtWidgets.QLabel(DynoTest1)
        self.label_3.setObjectName("label_3")
        self.verticalLayout_3.addWidget(self.label_3)
        self.label_2 = QtWidgets.QLabel(DynoTest1)
        self.label_2.setObjectName("label_2")
        self.verticalLayout_3.addWidget(self.label_2)
        self.label = QtWidgets.QLabel(DynoTest1)
        self.label.setObjectName("label")
        self.verticalLayout_3.addWidget(self.label)
        self.horizontalLayout.addLayout(self.verticalLayout_3)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.label_5 = QtWidgets.QLabel(DynoTest1)
        self.label_5.setObjectName("label_5")
        self.verticalLayout.addWidget(self.label_5)
        self.lcdNumber_4 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_4.setFrameShape(QtWidgets.QFrame.Box)
        self.lcdNumber_4.setFrameShadow(QtWidgets.QFrame.Raised)
        self.lcdNumber_4.setLineWidth(1)
        self.lcdNumber_4.setSmallDecimalPoint(True)
        self.lcdNumber_4.setDigitCount(5)
        self.lcdNumber_4.setMode(QtWidgets.QLCDNumber.Dec)
        self.lcdNumber_4.setSegmentStyle(QtWidgets.QLCDNumber.Filled)
        self.lcdNumber_4.setProperty("value", 0.0)
        self.lcdNumber_4.setObjectName("lcdNumber_4")
        self.verticalLayout.addWidget(self.lcdNumber_4)
        self.lcdNumber_5 = QtWidgets.QLCDNumber(DynoTest1)
        font = QtGui.QFont()
        font.setBold(False)
        font.setWeight(50)
        self.lcdNumber_5.setFont(font)
        self.lcdNumber_5.setSmallDecimalPoint(True)
        self.lcdNumber_5.setObjectName("lcdNumber_5")
        self.verticalLayout.addWidget(self.lcdNumber_5)
        self.lcdNumber_6 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_6.setSmallDecimalPoint(True)
        self.lcdNumber_6.setObjectName("lcdNumber_6")
        self.verticalLayout.addWidget(self.lcdNumber_6)
        self.horizontalLayout.addLayout(self.verticalLayout)
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.label_6 = QtWidgets.QLabel(DynoTest1)
        self.label_6.setObjectName("label_6")
        self.verticalLayout_2.addWidget(self.label_6)
        self.lcdNumber = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber.setSmallDecimalPoint(True)
        self.lcdNumber.setObjectName("lcdNumber")
        self.verticalLayout_2.addWidget(self.lcdNumber)
        self.lcdNumber_2 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_2.setSmallDecimalPoint(True)
        self.lcdNumber_2.setObjectName("lcdNumber_2")
        self.verticalLayout_2.addWidget(self.lcdNumber_2)
        self.lcdNumber_3 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_3.setSmallDecimalPoint(True)
        self.lcdNumber_3.setObjectName("lcdNumber_3")
        self.verticalLayout_2.addWidget(self.lcdNumber_3)
        self.horizontalLayout.addLayout(self.verticalLayout_2)
        self.horizontalLayout_2.addLayout(self.horizontalLayout)
        self.verticalLayout_5 = QtWidgets.QVBoxLayout()
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        self.label_7 = QtWidgets.QLabel(DynoTest1)
        self.label_7.setObjectName("label_7")
        self.verticalLayout_5.addWidget(self.label_7)
        self.lcdNumber_7 = QtWidgets.QLCDNumber(DynoTest1)
        self.lcdNumber_7.setObjectName("lcdNumber_7")
        self.verticalLayout_5.addWidget(self.lcdNumber_7)
        self.horizontalLayout_2.addLayout(self.verticalLayout_5)
        self.verticalLayout_4.addLayout(self.horizontalLayout_2)
        self.graphicsView = QtWidgets.QGraphicsView(DynoTest1)
        self.graphicsView.setStyleSheet("border-image: url(:/newPrefix/husky_head5.png);")
        self.graphicsView.setLineWidth(1)
        self.graphicsView.setObjectName("graphicsView")
        self.verticalLayout_4.addWidget(self.graphicsView)

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

    def retranslateUi(self, DynoTest1):
        _translate = QtCore.QCoreApplication.translate
        DynoTest1.setWindowTitle(_translate("DynoTest1", "DynoTest1"))
        self.pushButton_2.setText(_translate("DynoTest1", "Pause"))
        self.pushButton_4.setText(_translate("DynoTest1", "Print"))
        self.pushButton_3.setText(_translate("DynoTest1", "Stop"))
        self.pushButton.setText(_translate("DynoTest1", "Start"))
        self.label_3.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">RPMs</span></p></body></html>"))
        self.label_2.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Torque (ft-lbs)</span></p></body></html>"))
        self.label.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Horse Power</span></p></body></html>"))
        self.label_5.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Now</span></p></body></html>"))
        self.label_6.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Max</span></p></body></html>"))
        self.label_7.setText(_translate("DynoTest1", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">Run Time</span></p><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">(Seconds)</span></p></body></html>"))

import Resource_rc

图形用户界面的图片

推荐答案

首先是将 PlotWidget 添加到 GUI.为此,我们使用 QGraphicsView(实际上可以使用任何小部件),在 QGraphicsView 中我们添加一个布局,在这个布局中我们添加 PlotWidget.

The first thing is to add the PlotWidget to the GUI. For this we use QGraphicsView (in fact any widget can be used), in the QGraphicsView we add a layout, and in this layout we add the PlotWidget.

layout = QHBoxLayout()
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.graphicsView.setLayout(layout)

然后创建项目,如果您希望有 2 个轴并且在同一个图中,我们以下面的代码为例链接.

Then the items are created, and as you wish to have 2 axes and in the same plot we take as an example the code found in the following link.

在您要使用的示例中,使用计时器来更新数据,但在这种情况下,每次调用 onDataChanged 方法时,时钟都必须为其读取数据.为了获取视图,我们创建了一个过程来仅存储和显示最后 50 个元素.

In the example you wanted to use, use a timer to update the data, but in this case that clock must be reading data for it every time the onDataChanged method is called. To obtain a view, a procedure has been created to only store and display the last 50 elements.

代码:

class GUI(QWidget, Ui_DynoTest1):
    def __init__(self, parent=None):
        [...]
        self.thread.start()
        self.torque = []
        self.horse_power = []

        layout = QHBoxLayout()
        self.plot = pg.PlotWidget()
        layout.addWidget(self.plot)
        self.graphicsView.setLayout(layout)

        self.p1 = self.plot.plotItem
        self.p1.setLabels(left='Torque')
        self.TorqueCurve = self.p1.plot()
        self.TorqueCurve.setPen(pg.mkPen(color="#ff0000", width=2))

        self.p2 = pg.ViewBox()
        self.HorsePowerCurve = pg.PlotCurveItem()
        self.HorsePowerCurve.setPen(pg.mkPen(QColor(0, 255, 0)), width=2)
        self.p2.addItem(self.HorsePowerCurve)
        self.p1.scene().addItem(self.p2)
        self.p1.showAxis('right')
        self.p1.getAxis('right').setLabel('HorsePower', color='#0000ff')
        self.p1.getAxis('right').linkToView(self.p2)
        self.p1.vb.sigResized.connect(self.updateViews)

    def updateViews(self):
        self.p2.setGeometry(self.p1.vb.sceneBoundingRect())
        self.p2.linkedViewChanged(self.p1.vb, self.p2.XAxis)

    def onDataChanged(self, Force, RPM, Max_RPM, Torque, Max_Torque, HorsePower, Max_HorsePower, Run_Time):
        [...]
        if len(self.torque) < 50:
            self.torque.append(Torque)
        else:
            self.torque = self.torque[1:] + [Torque]

        if len(self.horse_power) < 50:
            self.horse_power.append(HorsePower)
        else:
            self.horse_power = self.horse_power[1:] + [HorsePower]
        self.TorqueCurve.setData(self.torque)
        self.HorsePowerCurve.setData(self.horse_power)
        self.updateViews()

这篇关于尝试使用 PyQt5 获取 GUI 的实时绘图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆