PyQtGraph嵌入QWidget中动态绘制曲线(固定横坐标比例,坐标系可拖动查看历史数据)

PyQtGraph嵌入QWidget中动态绘制曲线(固定横坐标比例,坐标系可拖动查看历史数据)


效果

在这里插入图片描述

说明

我看网上的大部分教程都无法固定坐标系比例,导致数据一多就会显得图像拥挤,很不美观;且实现固定的比例的大多是是通过列表的数据偏移做的(即data[:-1] = data[1:]),这种就会导致只能查看当前这段时间内的数据,无法查看历史数据。在查找了不少博客后,终于发现一种比较好的实现方式。

本文实现PyQtGraph在绘制过程中实时添加数据进行绘制,且固定横轴坐标系比例,并且可以在结束实时绘制后左右拖动坐标轴查看历史数据。


源码

import math
import sys
import pyqtgraph as pg
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout

from PyQt5.QtCore import QTimer


class Draw(QWidget):
    def __init__(self):
        super().__init__()
        self.timer = None
        self.resize(800, 800)
        self.setWindowTitle("Sin's dynamic curve")

        # 1.绘制板基本设置
        pg.setConfigOptions(leftButtonPan=True, antialias=True)  # 允许鼠标左键拖动画面,并启用抗锯齿
        pg.setConfigOption('background', 'w')  #初始的背景(白)

        # 2.创建 6 个坐标点组
        self.xRange = 80  # x坐标显示宽度
        self.x_points = list(range(0, 60))
        self.y_points = []
        for i in range(len(self.x_points)):
            self.y_points.append(math.sin(i / 10))
        # 点型 ['o', 's', 't', 't1', 't2', 't3','d', '+', 'x', 'p', 'h', 'star']
        # 点色 ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'd', 'l', 's']

        # 3.创建窗口,设置绘图样式
        self.pw = pg.PlotWidget(self)
        self.plot_data = self.pw.plot(self.x_points, self.y_points, pen=pg.mkPen(color=(0, 0, 100), width=3),
                                      symbol='s', symbolBrush='r')
        # 这里的 self.plot_data 是用于后续增加点的绘制

        # 4.将绘图板和按钮嵌入主窗体中
        self.start_btn = QPushButton('Start', self)
        self.start_btn.clicked.connect(self.timerStart)
        self.stop_btn = QPushButton('Stop', self)
        self.stop_btn.clicked.connect(self.timerStop)

        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.pw)
        self.v_layout.addWidget(self.start_btn)
        self.v_layout.addWidget(self.stop_btn)
        self.setLayout(self.v_layout)

        # 5.设置定时器
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.newPointPlot)

    def timerStart(self):
        self.timer.start(100)  # ms

    def timerStop(self):
        self.timer.stop()

    def newPointPlot(self):
        # 绘制时失能鼠标控制
        self.pw.setMouseEnabled(x=False, y=False)  # 失能x,y轴控制
        self.x_points.append(len(self.x_points))  # +1
        self.y_points.append(math.sin(self.x_points[-1] / 10))

        self.plot_data.setData(self.x_points, self.y_points)  # 重新绘制

        if(len(self.x_points) > self.xRange):
            self.pw.setXRange(len(self.x_points) - self.xRange, len(self.x_points))  # 固定x坐标轴宽度

        # 结束时使能鼠标控制
        self.pw.setMouseEnabled(x=True, y=False)  # 使能x轴控制,失能y轴控制


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Draw()
    demo.show()
    sys.exit(app.exec_())

参考

PYQT5+pyqtgraph 2d绘图实时刷新(坐标系跟着曲线一起移动,且可以查看绘制历史)的解决方法

  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现历史回放功能,需要读取存储在文件历史数据,然后按照时间顺序依次绘制曲线。以下是一个简单的实现步骤: 1. 创建一个Qt图形界面应用程序,并添加一个QCustomPlot控件用于绘制曲线。 2. 添加一个QPushButton控件用于触发历史回放功能,以及一个QFileDialog控件用于选择历史数据文件。 3. 在QPushButton的clicked()信号槽函数,使用QFileDialog打开历史数据文件,并读取文件的数据。 4. 将读取到的数据按时间顺序排序,并按照时间顺序依次绘制曲线。可以使用QTimer类来实现按时间顺序绘制曲线的功能。 5. 在绘制曲线时,可以使用QCPGraph控件来表示曲线,使用addData()函数向曲线添加数据点。 以下是一个示例代码: ``` #include "mainwindow.h" #include "ui_mainwindow.h" #include <QFileDialog> #include <QTimer> #include <QDateTime> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // 添加一个QCustomPlot控件用于绘制曲线 m_customPlot = new QCustomPlot(this); setCentralWidget(m_customPlot); // 添加一个QPushButton控件用于触发历史回放功能 m_playbackButton = new QPushButton("Playback", this); connect(m_playbackButton, &QPushButton::clicked, this, &MainWindow::onPlaybackButtonClicked); // 在工具栏添加QPushButton控件和QFileDialog控件 QToolBar *toolBar = addToolBar("Toolbar"); toolBar->addWidget(m_playbackButton); toolBar->addAction("Open", this, &MainWindow::onOpenFile); // 初始化QTimer用于按时间顺序绘制曲线 m_timer = new QTimer(this); connect(m_timer, &QTimer::timeout, this, &MainWindow::onTimerTimeout); } MainWindow::~MainWindow() { delete ui; } void MainWindow::onOpenFile() { // 使用QFileDialog打开历史数据文件 QString fileName = QFileDialog::getOpenFileName(this, "Open File", "", "Text Files (*.txt)"); if (fileName.isEmpty()) return; // 读取文件的数据 QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) return; QTextStream in(&file); m_data.clear(); while (!in.atEnd()) { QString line = in.readLine(); QStringList parts = line.split(','); if (parts.size() != 2) continue; QDateTime dateTime = QDateTime::fromString(parts[0], "yyyy-MM-dd HH:mm:ss.zzz"); double value = parts[1].toDouble(); m_data.append(qMakePair(dateTime, value)); } // 关闭文件 file.close(); // 按时间顺序排序 std::sort(m_data.begin(), m_data.end(), [](const QPair<QDateTime, double> &a, const QPair<QDateTime, double> &b){ return a.first < b.first; }); } void MainWindow::onPlaybackButtonClicked() { // 按时间顺序依次绘制曲线 if (m_data.isEmpty()) return; m_customPlot->clearGraphs(); QCPGraph *graph = m_customPlot->addGraph(); double minX = std::numeric_limits<double>::max(); double maxX = std::numeric_limits<double>::min(); for (int i = 0; i < m_data.size(); i++) { double x = m_data[i].first.toMSecsSinceEpoch() / 1000.0; double y = m_data[i].second; graph->addData(x, y); minX = qMin(minX, x); maxX = qMax(maxX, x); } m_customPlot->xAxis->setRange(minX, maxX); m_customPlot->yAxis->setRange(graph->data().valueRange().lower, graph->data().valueRange().upper); // 启动QTimer按时间顺序绘制曲线 m_timer->start(100); } void MainWindow::onTimerTimeout() { static int index = 0; if (index >= m_data.size()) { m_timer->stop(); return; } QCPGraph *graph = m_customPlot->graph(); double x = m_data[index].first.toMSecsSinceEpoch() / 1000.0; double y = m_data[index].second; graph->addData(x, y); m_customPlot->xAxis->setRange(m_customPlot->xAxis->range().lower, x); m_customPlot->yAxis->setRange(graph->data().valueRange().lower, graph->data().valueRange().upper); m_customPlot->replot(); index++; } ``` 该示例代码实现了一个简单的历史回放功能。在打开历史数据文件后,点击Playback按钮即可按时间顺序绘制曲线。在绘制曲线时,使用了QTimer按时间顺序依次绘制曲线

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值