zoukankan      html  css  js  c++  java
  • Qt QBarSeries简易柱状图教程

    博客园最强Qt QBarSeries简易柱状图教程

    前情提要

    每个人的绘图需求不同,此篇教程也是根据需求来改的。我的需求大概如下所示。

    • 通过信号槽的方式接收signals来刷新柱状图,所以每次触发信号,就要刷新一次柱状图。
    • 柱状图的横纵坐标,都是动态设置可变的。(通过信号传入的参数来改变)
    • 需要显示柱状图的值信息,即每根柱子的值
    • 最基础的当然就是没有bug,不崩溃

    准备工作

    • 在pro文件中添加charts模块
    QT += charts
    
    • 引用
    #include <QtCharts>
    

    方便起见,直接引用,不需要单独引用某一个模块。

    涉及对象介绍

    • QChartView

      用于存放QChart的控件,显示表格,在基础控件中不存在,需要手动将控件添加到“窗体”中。

    • QChart

      用于存放表格的对象,可以同时存放多个表格对象。

    • QBarSeries(某一种表格对象)

      用于存放此表格中所有的“柱子”对象。

    • QBarSet("柱子")

      用于显示一系列柱子。单个QBarSet的柱子数量应该根据对应显示的横纵坐标来设置。

    • QBarCategoryAxis

      将“柱子”分类的表格坐标。(横纵坐标均可,此教程中为横坐标)

      比如QBarCategoryAxis中的category个数为10,那么每个QBarSet都应该有10个值。

    • QValueAxis

      用于显示”柱子“值的坐标。(横纵坐标均可,此教程中为纵坐标)

    开始实战

    初始版本

    初始版本,直接初始化就显示一个完整的柱状图

    barSeries = new QBarSeries();
    barCategoryAxisX = new QBarCategoryAxis();
    valueAxisY = new QValueAxis();
    chart = new QChart();
    chartView = new QChartView(this);
    
    barOK = new QBarSet("OK");
    barNG = new QBarSet("NG");
    barNAN = new QBarSet("NAN");
    
    barOK->append(10);
    barNG->append(2);
    barNAN->append(3);
    
    barSeries->append(barOK);
    barSeries->append(barNG);
    barSeries->append(barNAN);
    
    barCategoryAxisX->append("Row1");
    
    valueAxisY->setRange(0,10);
    valueAxisY->setTickCount(3);//设置value网格数
    
    chart->addSeries(barSeries);
    chart->setAxisX(barCategoryAxisX, barSeries);
    chart->setAxisY(valueAxisY, barSeries);
    
    chart->setTitle(u8("检查结果柱状图"));
    chart->setAnimationOptions(QChart::SeriesAnimations);
    
    chartView->setRenderHint(QPainter::Antialiasing);
    chartView->setChart(chart);
    ui->verticalLayout->addWidget(chartView);
    

    这个,我相信大家都会,Qt的官方教程都有,但是如果需要通过信号槽来刷新呢?

    刷新版本

    既然是刷新版本,所以需要更新X、Y坐标轴,更新“柱子”的内容。

    • 因为都是通过指针的方式添加,所以最好的方式当然就是每个都clear重新分配内存。QBarSet除了手动析构外没有,比较好的办法,通过查询可知,可以通过QBarSeries来释放。
    barSeries.clear();
    barOK = new QBarSet("OK");
    barNG = new QBarSet("NG");
    barNAN = new QBarSet("NAN");
    
    barSeries->append(barOK);
    barSeries->append(barNG);
    barSeries->append(barNAN);
    
    • 至于横纵坐标,通过clear后重新设置即可。
    barCategoryAxisX->clear();
    barCategoryAxisX->append("Row1");
    
    valueAxisY->setRange(0, 10);//动态值
    valueAxisY->setTickCount(3);
    
    chart->setAxisX(barCategoryAxisX, barSeries);
    chart->setAxisY(valueAxisY, barSeries);
    

    至此,应该再次触发刷新,就可以了,但是很遗憾,添加上述函数,再次刷新,会导致程序崩溃。

    为什么呢?

    其实很简单,因为

    chart->setAxisX();
    

    这个函数会手动delete掉,设置后面的barSeries之前的那个series。因为都是同一个series,所以只要重新设置X、Y轴,就会删掉barSeries。

    但是无论你barSeries怎么修改,哪怕是重新new一个对象,好像都会崩溃。

    这个时候,查阅qt官方文档,你会发现,原来官方在设置X、Y之前还有一个createDefaultAxes()这个函数。随即在setAxisX()之前加上这句。

    chart->createDefaultAxes();
    

    然后,就会发现,崩溃是没有了,但是好像刷新之后啥都没有。

    仔细想想,可能是需要重新设置barSeries,于是分别添加了如下代码

    chart->removeAllSeries();
    chart->addSeries(barSeries);
    

    让chart也刷新一次。

    chartView->setChart(chart);
    

    可惜可惜,又崩溃了,其实很简单,removeAllSeries之后,barSeries对象被delete掉,需要重新分配内存,即

    chart->removeAllSeries();
    barSeries = new QBarSeries();
    chart->addSeries(barSeries);
    

    这样的话,刷新的时候,“柱子”有了。大致代码如下

    void flush()
    {
        barCategoryAxisX->clear();
        chart->removeAllSeries();
    	
        barSeries->clear();              
        barSeries = new QBarSeries();
    
        barOK = new QBarSet("OK");
        barNG = new QBarSet("NG");
        barNAN = new QBarSet("NAN");
        
        barSeries->append(barOK);
        barSeries->append(barNG);
        barSeries->append(barNAN);
        
        chart->createDefaultAxes();
        
        valueAxisY->setRange(0, 10);
        valueAxisY->setTickCount(3);
        
        //......append数据到barset
        
        chart->addSeries(barSeries);
        chart->setAxisX(barCategoryAxisX, barSeries);
        chart->setAxisY(valueAxisY, barSeries);
        
        chartView->setChart(chart);
    }
    

    显示值版本

    因为需求,我们需要将值显示到“柱子”上。查找资料可得到如下代码:

    barSeries->setLabelsPosition(QAbstractBarSeries::LabelsOutsideEnd);
    barSeries->setLabelsVisible(true);
    

    这样的确可以,显示值到“柱子”的上方,但是很遗憾,运行的时候,啥都没有,因为默认的barSet的labelColor为white,也就是跟背景色一致了。那么我们可以采取换背景色的方案,也可以采取换label颜色的方案。这里采取换label颜色的方案。

    label的显示设置取决于barSeries,但是,找遍了chart和barSeries都没有找到关于label字体、颜色等参数的设置,最后在barset中找到了setLabel相关的参数。

    barOK->setLabelColor(Qt::black);
    barNG->setLabelColor(Qt::black);
    barNAN->setLabelColor(Qt::black);
    

    这样就可以正常显示值了。

    到这里,本片教程就结束了,坑确实蛮多的,资料比较少,希望能帮到大家。

  • 相关阅读:
    luogu_1168: 中位数
    luogu_4762: [CERC2014]Virus synthesis
    luogu_4287:双倍回文
    回文自动机学习笔记
    luogu_3645: 雅加达的摩天楼
    python爬今日头条(ajax分析)
    Python多进程multiprocessing.Pool()
    Python爬微博(ajax+mongo)
    python实用函数之join()
    python之tuple与list
  • 原文地址:https://www.cnblogs.com/ligiggy/p/15304240.html
Copyright © 2011-2022 走看看