zl程序教程

您现在的位置是:首页 >  工具

当前栏目

qt widgets chartview曲线图绘制(解决动态刷新内存过大问题)

Qt内存 解决 动态 绘制 刷新 过大 问题
2023-09-27 14:29:08 时间

本文主要讲解如何动态绘制曲线图,并处理会遇到的一些问题,让程序能稳定持续运行

经过在网上的查询,发现大部分 都是推荐使用 replace用法,因为append的用法随着时间会出现一些问题,我就将这两种方法分享一下各自的效果和使用心得。

1.replace

根据单词的意思就能知道这个函数的作用,意思就是替换,使用这个函数就不在适用scroll偏移效果了,就在一个曲线表,行和列是某一定值,然后刷新曲线就用replace将x轴新的点替换旧的点, 就可以实现图形的 更新了

代码部分:

.h

#ifndef THEMEWIDGET_H
#define THEMEWIDGET_H

#include <QtWidgets/QWidget>
#include <QtCharts/QChartGlobal>
#include <QTime>
#include <QTimer>

QT_BEGIN_NAMESPACE
class QComboBox;
class QCheckBox;
class Ui_ThemeWidgetForm;
QT_END_NAMESPACE

QT_CHARTS_BEGIN_NAMESPACE
class QChartView;
class QChart;
QT_CHARTS_END_NAMESPACE

typedef QPair<QPointF, QString> Data;
typedef QList<Data> DataList;
typedef QList<DataList> DataTable;

QT_CHARTS_USE_NAMESPACE

class ThemeWidget: public QWidget
{
    Q_OBJECT
public:
    explicit ThemeWidget(QWidget *parent = 0);
    ~ThemeWidget();

private Q_SLOTS:
    void updateUI();

private:
    void populateThemeBox();
    void populateAnimationBox();
    void populateLegendBox();
    void connectSignals();

    QChart *createLineChart() const;
private slots:
    void timeSlot();
private:

    int m_valueMax;
    int m_valueCount;
    QList<QChartView *> m_charts;

    //DataTable m_dataTable;
    QChartView *chartView;
    QTimer *timer;
    Ui_ThemeWidgetForm *m_ui;

};

#endif /* THEMEWIDGET_H */

.cpp

#include "themewidget.h"
#include "ui_themewidget.h"

QLineSeries *series;
QValueAxis *axisX;
QChart *chart;

QString aaa;
QString ids;
unsigned long num=100;
int chardate[256];
int nowdate[256];
int lastdate[256];
static int rxnum=0,currectnum=0;
ThemeWidget::ThemeWidget(QWidget *parent) :
    QWidget(parent),
    m_ui(new Ui_ThemeWidgetForm)
{
    m_ui->setupUi(this);
    
    //初始化表格配置
    m_valueMax=255;
    m_valueCount=255;
    populateThemeBox();
    chartView = new QChartView(createLineChart());
    QGridLayout *baseLayout = new QGridLayout(); //便于显示,创建网格布局
    baseLayout->addWidget(chartView, 0, 0);
   // m_ui->gridLayout->addWidget(chartView, 1 , 1);
    m_ui->gridLayout->addLayout(baseLayout,1,1);
    chartView->setRenderHint(QPainter::Antialiasing);
    m_charts << chartView;
    //设置初始表格颜色
    QPalette pal = qApp->palette();
    pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
    pal.setColor(QPalette::WindowText, QRgb(0x404044));
    qApp->setPalette(pal);

    //创建定时器
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timeSlot()));//绑定定时函数
    timer->start(20);

}

void ThemeWidget::timeSlot()
{
    for(int i=0;i<256;i++){
          nowdate[i]=qrang()%1000*0.15;//提供一个随机数
       // qDebug()<<nowdate[i];
    }
    for(int i=0;i<256;i++){
        series->replace(i,lastdate[i],i,nowdate[i]);//采用replace方式,比append串行方式节省内存,不会造成长时间运行电脑严重卡顿或者程序崩溃问题
        lastdate[i]=nowdate[i];//新数据使用完保存到旧数据数组里,下次replace用
    }


}

ThemeWidget::~ThemeWidget()
{
    delete m_ui;
}
//初始化chart配置
QChart *ThemeWidget::createLineChart() const
{
    chart = new QChart();
    chart->setTitle("UDP数据曲线图");
    QString name("UDP Data");
    series = new QLineSeries();
    series->setName(name);
    for(int i=0;i<256;i++){//初始化图形数值
        nowdate[i]=0;
        series->append(i,nowdate[i]);
        lastdate[i]=nowdate[i];//记录初始化的y值
    }
    chart->addSeries(series);
    chart->createDefaultAxes();
    chart->axisX()->setRange(0, m_valueMax);
    //chart->axisY()->setRange(-m_valueCount, m_valueCount); //设置y轴坐标有正负,但数据未说明有负值
    chart->axisY()->setRange(0, m_valueCount);//这里设置y轴坐标 只有正值
    axisX=new QValueAxis;
    //append要按照大小顺序依次添加
    axisX->setTickCount(5);//设置背景表格有5列
    chart->setAxisX(axisX,series);
    return chart;
}
//下拉模式选择
void ThemeWidget::populateThemeBox()
{
    // add items to theme combobox
    m_ui->themeComboBox->addItem("Light", QChart::ChartThemeLight);
    m_ui->themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
    m_ui->themeComboBox->addItem("Dark", QChart::ChartThemeDark);
    m_ui->themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
    m_ui->themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
    m_ui->themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
    m_ui->themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
    m_ui->themeComboBox->addItem("Qt", QChart::ChartThemeQt);
}
void ThemeWidget::updateUI()
{
    //设置主题颜色
    QChart::ChartTheme theme = static_cast<QChart::ChartTheme>(
                m_ui->themeComboBox->itemData(m_ui->themeComboBox->currentIndex()).toInt());
    const auto charts = m_charts;
    if (!m_charts.isEmpty() && m_charts.at(0)->chart()->theme() != theme)
    {
        for (QChartView *chartView : charts) {
            chartView->chart()->setTheme(theme);
        }
        // Set palette colors based on selected theme
        //![8]
        QPalette pal = window()->palette();
        if (theme == QChart::ChartThemeLight) {
            pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        //![8]
        } else if (theme == QChart::ChartThemeDark) {
            pal.setColor(QPalette::Window, QRgb(0x121218));
            pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
        } else if (theme == QChart::ChartThemeBlueCerulean) {
            pal.setColor(QPalette::Window, QRgb(0x40434a));
            pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
        } else if (theme == QChart::ChartThemeBrownSand) {
            pal.setColor(QPalette::Window, QRgb(0x9e8965));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        } else if (theme == QChart::ChartThemeBlueNcs) {
            pal.setColor(QPalette::Window, QRgb(0x018bba));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        } else if (theme == QChart::ChartThemeHighContrast) {
            pal.setColor(QPalette::Window, QRgb(0xffab03));
            pal.setColor(QPalette::WindowText, QRgb(0x181818));
        } else if (theme == QChart::ChartThemeBlueIcy) {
            pal.setColor(QPalette::Window, QRgb(0xcee7f0));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        } else {
            pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        }
        window()->setPalette(pal);
    }
}

通过以上代码就可以实现chart动态更新显示,把每次随机生成的点使用完时候保存到数组中,然后在下一次更新图像的时候replace就可以找到坐标对应的旧点,再用新的点去替换,就没有问题啦。

    void replace(qreal oldX, qreal oldY, qreal newX, qreal newY);
    void replace(const QPointF &oldPoint, const QPointF &newPoint);
    void replace(int index, qreal newX, qreal newY);
    void replace(int index, const QPointF &newPoint);

这里replace采用的是第一种方式。


2.append