Qt学习【3】绘制动态折线图

本文详细介绍如何在Qt中创建并动态更新折线图,包括使用QLineSeries添加数据点,通过QChart显示数据,以及利用QChartView进行图表展示。文章还提供了动态更新折线图的方法,如使用定时器和调整坐标轴范围。
摘要由CSDN通过智能技术生成


一个简单的折线图

打开欢迎界面中的示例,搜索linechart,点击Running the Example,打开示例。

1、改pro工程文件

Qt Charts作为一个独立的模块,在使用前需要在项目的pro文件中添加:

QT += charts

2、包含头文件,并引用qt chart空间命名

// 包含line chart需要的头文件
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>

// 引用命名空间
QT_CHARTS_USE_NAMESPACE

3、创建QLineSeries并添加数据

​ 折线图的实现需要创建一个QLineSeries对象用于保存和绘制折线数据:

QLineSeries *series = new QLineSeries();
series->append(0, 6);
series->append(2, 4);
series->append(3, 8);
series->append(7, 4);
series->append(10, 5);
*series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) <<QPointF(20, 2);

4、创建QChart用于显示数据

​ 创建好series后,需要创建一个QChart实例并关联series,创建坐标才能将数据显示出来:

QChart *chart = new QChart();
chart->legend()->hide();
chart->addSeries(series);
chart->createDefaultAxes();
chart->setTitle("Simple line chart example");

5、创建QChartView对象并显示图表

这里创建QChartView对象是为了将最终结果显示到界面,如果不想用QChartView,也可以选择QGraphicsView scene来显示。

QChartView *chartView = new QChartView(chart);
// 开启抗锯齿,让显示效果更好
chartView->setRenderHint(QPainter::Antialiasing);

官方源码

#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>

QT_CHARTS_USE_NAMESPACE

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

//![1]
    QLineSeries *series = new QLineSeries();
//![1]

//![2]
    series->append(0, 6);
    series->append(2, 4);
    series->append(3, 8);
    series->append(7, 4);
    series->append(10, 5);
    *series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2);
//![2]

//![3]
    QChart *chart = new QChart();
    chart->legend()->hide();
    chart->addSeries(series);
    chart->createDefaultAxes();
    chart->setTitle("Simple line chart example");
//![3]

//![4]
    QChartView *chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing);
//![4]


//![5]
    QMainWindow window;
    window.setCentralWidget(chartView);
    window.resize(400, 300);
    window.show();
//![5]

    return a.exec();
}

绘制动态折线图

1、使用QChart::scroll(qreal dx, qreal dy)函数

参考官方示例Dynamic Spline Example。

使用定时器,连接定时器timeout()信号、handleTimeout()槽函数,每过1000ms进入槽函数处理。

槽函数:

void Chart::handleTimeout()
{
    qreal x = plotArea().width() / m_axis->tickCount();
    qreal y = (m_axis->max() - m_axis->min()) / m_axis->tickCount();
    m_x += y;
    m_y = qrand() % 5 - 2.5;
    m_series->append(m_x, m_y);
    scroll(x, 0);
    if (m_x == 100)
        m_timer.stop();
}

scroll()函数可以滚动表格,根据可见范围的特定距离。

2、改变横坐标轴的范围

QDateTimeAxis::setRange(QDateTime min, QDateTime max)函数可以设置时间横坐标轴的范围,从而达到折线图动态横移的效果。

void MainWindow::timerEvent(QTimerEvent *event)
{
    static int i = 0;
    if(i++ == 10)
    {
        i = 0;
        qDebug() << "timer";
    }
    QDateTime t(QDateTime::currentDateTime());

    dseries->append(t.toMSecsSinceEpoch(),(qrand()%10));
    QDateTime xMax;// 设置时间坐标轴范围
    xMax = QDateTime::currentDateTime();

    if(xMax > daxisX->max())
    {
        QDateTime xMin;
        xMin = xMax.addSecs(qint64(-20));
        daxisX->setRange(xMin,xMax);
    }
}

 

------------------------------------------------------源文件------------------------------------

头文件mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    void paintEvent(QPaintEvent *event);
};

#endif // MAINWINDOW_H

mainwindow.cpp文件

#include "mainwindow.h"
#include <QDebug>

int xAxisData[10];
int yAxisData[10];
int oldxData[10];
int oldyData[10];
QList<QPointF> pointList;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTimer *timer = new QTimer(this);
    this->startTimer(1000);
    // 按键
    button = new QPushButton(this);
    button->setText("KEY");
    button->move(400,20);
    connect(button,&QPushButton::clicked,this,&this->button_slot);

    // 按键1
    button1 = new QPushButton(this);
    button1->setText("KEY1");
    button1->move(400,40);
    connect(button1,&QPushButton::clicked,this,&this->button1_slot);

    // 按键2
    button2 = new QPushButton(this);
    button2->setText("KEY2");
    button2->move(400,70);
    connect(button2,&QPushButton::clicked,this,&this->button2_slot);

    // 设置轴坐标
    axisX = new QValueAxis;
    axisX->setRange(0, 10);
    axisX->setTickCount(10);  // 设置轴坐标网格数
    axisX->setLabelFormat("%.1f");

    // 设置轴坐标
    axisY = new QValueAxis;
    axisY->setRange(0, 10);
    axisY->setTickCount(5);  // 设置轴坐标网格数
    axisY->setLabelFormat("%d");

    QPen pen;
    pen.setWidth(3);
    pen.setColor(Qt::red);

    series = new QLineSeries;
    series->setPen(pen);

    chart = new QChart;
    chart->addSeries(series);
    chart->setTitle("坐标图");
    chart->setAxisX(axisX,series);
    chart->setAxisY(axisY,series);
    chart->legend()->hide(); // 隐藏图例

    chartView = new QChartView(chart,this);
    chartView->setRenderHint(QPainter::Antialiasing);
    chartView->resize(400,200);
    chartView->move(20,20);

    // 设置轴坐标
    daxisX = new QDateTimeAxis;
    daxisX->setTickCount(5);  // 设置轴坐标网格数
    daxisX->setFormat("h:mm:ss");
    QDateTime xMin,xMax;// 设置时间坐标轴范围
    xMin = QDateTime::currentDateTime();
    xMax = xMin.addSecs(20);
    daxisX->setRange(xMin,xMax);

    // 设置轴坐标
    daxisY = new QValueAxis;
    daxisY->setRange(0, 10);
    daxisY->setTickCount(5);  // 设置轴坐标网格数
    daxisY->setLabelFormat("%d");

    QPen dpen;
    dpen.setWidth(3);
    dpen.setColor(Qt::red);

    dseries = new QLineSeries;
    dseries->setPen(pen);

    dchart = new QChart;
    dchart->addSeries(dseries);
    dchart->setTitle("坐标图");
    dchart->setAxisX(daxisX,dseries);
    dchart->setAxisY(daxisY,dseries);
    dchart->legend()->hide(); // 隐藏图例

    dchartView = new QChartView(dchart,this);
    dchartView->setRenderHint(QPainter::Antialiasing);
    dchartView->resize(400,200);
    dchartView->move(20,260);
}

MainWindow::~MainWindow()
{

}

void MainWindow::button_slot()
{
    static int j = 0, k = 0;
    qDebug() << "button";
    if(k == 0)
    {
        k = 1;
        for(int i=0;i<10;i++)
        {
            oldxData[i] = -1 + i;
            series->append(oldxData[i],oldyData[i]);
        }
    }
    else
    {
        for(int i=0;i<10;i++)
        {
            xAxisData[i] = oldxData[i] + 1;
            if(i!=9)yAxisData[i] = yAxisData[i+1];
            else{
                yAxisData[9] = qrand() % 10;
                axisX->setRange(xAxisData[0],xAxisData[9]);
            }
            series->remove(oldxData[i],oldyData[i]);
            series->append(xAxisData[i],yAxisData[i]);
            oldxData[i] = xAxisData[i];
            oldyData[i] = yAxisData[i];
        }
    }
}

void MainWindow::button1_slot()
{
    qDebug() << "button1";
    QDateTime t(QDateTime::currentDateTime());

    dseries->append(t.toMSecsSinceEpoch(),(qrand()%10));
    QDateTime xMax;// 设置时间坐标轴范围
    xMax = QDateTime::currentDateTime();

    if(xMax > daxisX->max())
    {
        QDateTime xMin;
        xMin = xMax.addSecs(qint64(-20));
        daxisX->setRange(xMin,xMax);
    }
}

/* 使用list队列添加折线图的点
 * 1、创建list
 * 2、按下按键,添加一个QPointF点到list内,刷新series内的点
 * 3、如果添加的个数大于10个需要:1)移动轴坐标 2)删除列表尾,删除曲线集的最后一个
 *
 *
*/
void MainWindow::button2_slot()
{
    qDebug() << "button2";
    static int i = 0;
    QPointF p11(i,(qrand()%10));
    pointList.append(p11);
    series->append(p11);
    if(pointList.isEmpty() == false && pointList.count() > 10)
    {
        series->remove(*(pointList.begin()));
        pointList.removeFirst();
        qreal a1 =0, a2 = 0;
        a1 = pointList.back().rx();
        a2 = pointList.front().rx();
        axisX->setRange(a2,a1);
    }
    i++;
}

void MainWindow::timerEvent(QTimerEvent *event)
{
    static int i = 0;
    if(i++ == 10)
    {
        i = 0;
        qDebug() << "timer";
    }
    QDateTime t(QDateTime::currentDateTime());

    dseries->append(t.toMSecsSinceEpoch(),(qrand()%10));
    QDateTime xMax;// 设置时间坐标轴范围
    xMax = QDateTime::currentDateTime();

    if(xMax > daxisX->max())
    {
        QDateTime xMin;
        xMin = xMax.addSecs(qint64(-20));
        daxisX->setRange(xMin,xMax);
    }
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值