Real-Time

50 Hz streaming with scrolling window using appendData().

Live Data Stream

Source Code

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QTimer>
#include <QDateTime>
#include <cmath>
#include <cstdlib>

#include "AZPlottingClass.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    QWidget window;
    window.setWindowTitle("Real-Time Plotting Demo");
    window.resize(800, 500);
    
    QVBoxLayout *mainLayout = new QVBoxLayout(&window);
    mainLayout->setContentsMargins(10, 10, 10, 10);
    
    // Plot
    AZPlottingClass *plot = new AZPlottingClass(&window);
    plot->setTitle("Live Data Stream (50 Hz)");
    plot->setXAxisLabel("Time (s)");
    plot->setYAxisLabel("Signal");
    plot->applyProfessionalStyle();
    plot->setInteractive(true, true);
    plot->setGridVisible(true, false);
    
    // Create empty series with scrolling window
    int seriesId = plot->addDataSeries(QVector<double>(), QVector<double>(), 
                                        "Live Signal", Qt::blue,
                                        AZPlottingClass::LineStyle::Solid, 1.5);
    plot->setScrollingWindow(seriesId, 5.0);  // Show last 5 seconds
    plot->setYAxisRange(-2.5, 2.5);
    plot->setXAxisRange(0, 5);
    
    mainLayout->addWidget(plot, 1);
    
    // Control bar
    QHBoxLayout *controlLayout = new QHBoxLayout();
    
    QPushButton *startBtn = new QPushButton("Start");
    QPushButton *stopBtn = new QPushButton("Stop");
    QPushButton *clearBtn = new QPushButton("Clear");
    QLabel *countLabel = new QLabel("Samples: 0");
    QLabel *fpsLabel = new QLabel("FPS: --");
    
    controlLayout->addWidget(startBtn);
    controlLayout->addWidget(stopBtn);
    controlLayout->addWidget(clearBtn);
    controlLayout->addSpacing(20);
    controlLayout->addWidget(countLabel);
    controlLayout->addWidget(fpsLabel);
    controlLayout->addStretch();
    
    mainLayout->addLayout(controlLayout);
    
    // State
    int sampleCount = 0;
    qint64 lastFpsTime = 0;
    int frameCount = 0;
    int currentSeriesId = seriesId;
    
    // Timer for updates
    QTimer *timer = new QTimer(&window);
    
    auto updatePlot = [&]() {
        double t = sampleCount * 0.02;  // 50 Hz
        double noise = (std::rand() % 100 - 50) / 100.0;
        double value = std::sin(t * 2) + 0.3 * std::sin(t * 7.3) + noise * 0.3;
        
        plot->appendData(currentSeriesId, t, value);
        plot->replotQueued();
        
        sampleCount++;
        frameCount++;
        countLabel->setText(QString("Samples: %1").arg(sampleCount));
        
        // Calculate FPS every second
        qint64 now = QDateTime::currentMSecsSinceEpoch();
        if (now - lastFpsTime >= 1000) {
            fpsLabel->setText(QString("FPS: %1").arg(frameCount));
            frameCount = 0;
            lastFpsTime = now;
        }
    };
    
    QObject::connect(timer, &QTimer::timeout, updatePlot);
    
    QObject::connect(startBtn, &QPushButton::clicked, [&]() {
        lastFpsTime = QDateTime::currentMSecsSinceEpoch();
        timer->start(20);  // 50 Hz
    });
    
    QObject::connect(stopBtn, &QPushButton::clicked, [timer]() {
        timer->stop();
    });
    
    QObject::connect(clearBtn, &QPushButton::clicked, [&]() {
        timer->stop();
        plot->clearData();
        currentSeriesId = plot->addDataSeries(QVector<double>(), QVector<double>(),
                                              "Live Signal", Qt::blue,
                                              AZPlottingClass::LineStyle::Solid, 1.5);
        plot->setScrollingWindow(currentSeriesId, 5.0);
        plot->setXAxisRange(0, 5);
        sampleCount = 0;
        frameCount = 0;
        countLabel->setText("Samples: 0");
        fpsLabel->setText("FPS: --");
    });
    
    window.show();
    return app.exec();
}