博客园最强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);

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

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

Qt QBarSeries简易柱状图教程的更多相关文章

  1. Qt快速入门系列教程目录

    Qt快速入门系列教程目录

  2. Git GUI简易使用教程

    Git GUI简易使用教程:先上图~~~~~ 一. 先从添加文件开始讲(先上图): 1.选中要添加的文件,点击菜单栏的“提交”,选中“缓存为提交”,

  3. Android简易实战教程--第五十一话《使用Handler实现增加、减少、暂停计数》

    转载博客请注明出处:道龙的博客 之前,写过一篇使用异步任务AysncTask实现倒计时的小案例,喜欢的话可以参考博客:Android简易实战教程--第三十三话< AsyncTask异步倒计时&g ...

  4. Android简易实战教程--第五十话《动画扫描》

    祝新年快乐!2017(一起)前行. 转载博客请注明出处:道龙的博客 本篇简答的小案例,使用动画知识,完成一个类似雷达扫描效果,并且加入自定义进度条.对于自定义进度条前面有很详细的解析和案例了,本篇就结 ...

  5. Android简易实战教程--第十六话《SharedPreferences保存用户名和密码》

    之前在Android简易实战教程--第七话<在内存中存储用户名和密码> 那里是把用户名和密码保存到了内存中,这一篇把用户名和密码保存至SharedPreferences文件.为了引起误导, ...

  6. Web压力测试工具 LoadRunner12.x简易入门教程--(一)回放与录制

        LoadRunner12.x简易入门教程--(一)回放与录制 今天在这里分享一下LoadRunner12.x版本的入门使用方法,希望对刚接触LoadRunner的童鞋有所帮助. LoadRun ...

  7. Windows+QT+Eclipse+MinGW搭建QT开发环境详细教程

     Windows+QT+Eclipse+MinGW搭建QT开发环境详细教程 一.准备工具: QT-SDK for Windows:http://get.qt.nokia.com/qtsdk/qt-sd ...

  8. 【Linux开发】【Qt开发】ARM QT移植详细步骤教程

    ARM QT移植详细步骤教程 米尔SAM9X5和A5D3X上默认的Qt版本是4.5.3,当这个版本的Qt库不能满足实际开发需求时,可通过此方法制定Qt开发.运行环境. 移植的步骤如下: 1.下载新版q ...

  9. Qt项目简易开发原理及常见问题解决

    一.资源下载地址 https://www.aliyundrive.com/s/jBU2wBS8poH 本项目路径:项目->免费->QtDev 注释:为了方便qt全功能开发,QtDev中包含 ...

随机推荐

  1. php 图片转换二进制数

    $image = "1.jpg"; //图片地址 $fp = fopen($image, 'rb'); $content = fread($fp, filesize($image) ...

  2. DevStream 成为 CNCF Sandbox 项目啦!- 锣鼓喧天、鞭炮齐鸣、红旗招展、忘词了。

    开局两张图,内容全靠"编" 来,有图有真相! DevStream ️ CNCF DevStream joins CNCF Sandbox CNCF Cloud Native Int ...

  3. JS:this关键字1

    this 代表了当前的对象,哪个对象调用了this所在的函数,this就代表了哪个对象: 例1: function fn(){ var a = 1; console.log(this) } fn() ...

  4. 实现领域驱动设计 - 使用ABP框架 - 创建实体

    用例演示 - 创建实体 本节将演示一些示例用例并讨论可选场景. 创建实体 从实体/聚合根类创建对象是实体生命周期的第一步.聚合/聚合根规则和最佳实践部分建议为Entity类创建一个主构造函数,以保证创 ...

  5. 编程技巧│提高 Javascript 代码效率的技巧

    目录 一.变量声明 二.三元运算符 三.解构赋值 四.解构交换 五.箭头函数 六.字符串模版 七.多值匹配 八.ES6对象简写 九.字符串转数字 十.次方相乘 十一.数组合并 十二.查找数组最大值最小 ...

  6. 一文掌握GitHub Actions基本概念与配置

    CI/CD包含很多流程,如拉取代码.测试.构建打包.登录远程服务器.部署发布等等. 而Github Actions是GitHub推出的一个CI/CD工具,类似工具还有TravisCI.Jenkins等 ...

  7. 微服务探索之路04篇k8s增加子节点,metrics资源监控,ingress-nginx域名配置及https配置

    1 k8s增加子节点 1.1 子节点服务器安装docker,使用脚本自动安装 curl -fsSL https://get.docker.com | bash -s docker --mirror A ...

  8. Burnside 引理与 Pólya 定理

    群 群的定义 在数学中,群是由一种集合以及一个二元运算所组成的,符合"群公理"的代数结构. 一个群是一个集合 \(G\) 加上对 \(G\) 的二元运算.二元运算用 \(\cdot ...

  9. AOP-动态代理

    动态代理的原理代理设计模式的原理:使用一个代理将原本对象包装起来,然后用该代理对象"取代"原始对象.任何对原始对象的调用都要通过代理.代理对象决定是否以及何时将方法调用转到原始对象 ...

  10. 【主流技术】Redis 在 Spring 框架中的实践

    前言 在Java Spring 项目中,数据与远程数据库的频繁交互对服务器的内存消耗比较大,而 Redis 的特性可以有效解决这样的问题. Redis 的几个特性: Redis 以内存作为数据存储介质 ...