(四)QCustomPlot柱形图动态显示实例开发

news2025/7/19 10:13:38

系列文章目录

提示:这里是该系列文章的所有文章的目录
第一章: (一)QCustomPlot常见属性设置、多曲线绘制、动态曲线绘制、生成游标、矩形放大等功能实现
第二章: (二)QCustomPlot生成热力图/矩阵颜色图
第三章: (三)Qt+QCustomPlot生成上下方向/不同颜色的条形图(柱形图)


文章目录

  • 系列文章目录
  • 前言
  • 一、QCustomPlot的提升
  • 二、示例完整代码展示
  • 三、下载链接
  • 总结


前言

接上一篇文章,在前文中实现的一个柱形图数据都是固定的,无法通过模拟按钮来进行数据的增加,并且数据量较小,无法体现实际项目中所需要的功能。所以在这一篇文章中进行了数据的模拟增加,并且可以动态显示界面,也可以清空图表进行重绘,详细功能实现见文章内容,大家可以参考学习,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、QCustomPlot的提升

本文在ui界面上添加了两个widget控件,并将其提升为QCustomPlot类,具体的提升步骤可见此博客:QCustomPlot常见属性设置、多曲线绘制、动态曲线绘制、生成游标、矩形放大等功能实现
请添加图片描述

由于界面上有多个QCustomPlot,所以在我们的构造函数中需要对这两个控件进行初始化,两个控件背景等等都是一样的,所以这里使用了一个setBarCustomPlot()函数通过输入形参的方式来完成两个控件的初始化,见下文示例完整代码。

void Widget::initWidget()
{
	...
	m_customPlot = new QCustomPlot();
    m_customPlot = ui->customplot;
    setBarCustomPlot(m_customPlot,0);

    m_customPlot_2 = new QCustomPlot();
    m_customPlot_2 = ui->customplot_2;
    setBarCustomPlot(m_customPlot_2,1);
    ...

二、示例完整代码展示

这里将示例的完整代码进行展示,详情见代码注释
1.widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "CustomPlot/qcustomplot.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void initWidget();
    void setBarCustomPlot(QCustomPlot *customPlot,int index);
    void setBarReplot(QCustomPlot *customPlot);

protected:
    bool eventFilter(QObject *watched,QEvent *event);

private slots:
    void on_pb_Start_clicked();
    void on_pb_Replot_clicked();
    void on_pb_Change_clicked();

private:
    Ui::Widget *ui;

    QCustomPlot *m_customPlot;
    QCustomPlot *m_customPlot_2;
    QCPItemText *maxLabel[2];
    QCPItemText *minLabel[2];

    int serialNum;
    double maxNum;
    double minNum;
    double xNum;
    double yNum;
};
#endif // WIDGET_H

2.widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->initWidget();
}

Widget::~Widget()
{
    delete m_customPlot;
    delete ui;
}

void Widget::initWidget()
{
    //初始化变量
    serialNum = 0;
    maxNum = 0;
    minNum = 0;
    xNum = 0;
    yNum = 0;

    m_customPlot = new QCustomPlot();
    m_customPlot = ui->customplot;
    setBarCustomPlot(m_customPlot,0);

    m_customPlot_2 = new QCustomPlot();
    m_customPlot_2 = ui->customplot_2;
    setBarCustomPlot(m_customPlot_2,1);

    //添加事件过滤器
    ui->customplot->installEventFilter(this);
    ui->customplot_2->installEventFilter(this);
}

void Widget::setBarCustomPlot(QCustomPlot *customPlot,int index)
{
    //qDebug()<<"*customPlot:"<<customPlot->objectName();

    //设置背景黑色
    customPlot->axisRect()->setBackground(QBrush(Qt::black));

    //x轴设置
    customPlot->xAxis->setVisible(true);
    customPlot->xAxis->setTickLabels(false);
    customPlot->xAxis->setSubTickLength(0);
    customPlot->xAxis->setTickLength(0);
    customPlot->xAxis->setRange(0,30);

    //x2轴设置
    customPlot->xAxis2->setVisible(true);
    customPlot->xAxis2->setTickLabels(false);
    customPlot->xAxis2->setSubTickLength(0);
    customPlot->xAxis2->setTickLength(0);

    //y轴设置
    customPlot->yAxis->setVisible(true);
    customPlot->yAxis->setTickLabels(false);
    customPlot->yAxis->setSubTickLength(0);
    customPlot->yAxis->setTickLength(0);
    customPlot->yAxis->setRange(-1.6,1.6);
    customPlot->yAxis->ticker()->setTickCount(3);
    customPlot->yAxis->grid()->setPen(QPen(Qt::white));

    //y2轴设置
    customPlot->yAxis2->setVisible(true);
    customPlot->yAxis2->setTickLabels(false);
    customPlot->yAxis2->setSubTickLength(0);
    customPlot->yAxis2->setTickLength(0);

    //设置文本框
    maxLabel[index] = new QCPItemText(customPlot);   //在QCustomplot中新建文字框
    maxLabel[index]->position->setType(QCPItemPosition::ptAxisRectRatio);   //位置类型
    maxLabel[index]->position->setCoords(0.96,0.18);
    maxLabel[index]->setText("   ");
    maxLabel[index]->setColor(QColor(Qt::white));   //字体颜色
    maxLabel[index]->setFont(QFont(font().family(),8));   //字体大小
    maxLabel[index]->setBrush(QColor(Qt::red));
    maxLabel[index]->setPadding(QMargins(2,2,2,2));   //文字距离边框几个像素

    minLabel[index] = new QCPItemText(customPlot);
    minLabel[index]->position->setType(QCPItemPosition::ptAxisRectRatio);
    minLabel[index]->position->setCoords(0.96,0.82);
    minLabel[index]->setText("   ");
    minLabel[index]->setColor(QColor(Qt::white));
    minLabel[index]->setFont(QFont(font().family(),8));
    minLabel[index]->setBrush(QColor(Qt::red));
    minLabel[index]->setPadding(QMargins(2,2,2,2));

}

void Widget::setBarReplot(QCustomPlot *customPlot)
{
    QCPBars *bars = new QCPBars(customPlot->xAxis,customPlot->yAxis);
    bars->setAntialiased(false);   //为了更好的边框效果,关闭抗齿锯
    bars->setWidth(1);   //设置各柱之前无间隔
    bars->setPen(QPen(QColor(Qt::black).lighter(100)));   //设置柱状图的边框颜色
    qDebug()<<"maxNum:"<<maxNum<<"   minNum:"<<minNum;

    if((yNum>minNum*0.8)&&(yNum<maxNum*0.8))
    {
        bars->setBrush(QColor(Qt::green));//绿色
    }
    else if((yNum<minNum)||(yNum>maxNum))
    {
        bars->setBrush(QColor(Qt::red));//红色
    }
    else
    {
        bars->setBrush(QColor(Qt::yellow));//黄色
    }

    QVector<double> ticks1;
    ticks1 << xNum;
    QVector<double> fossilData1;
    fossilData1  << yNum;
    bars->setData(ticks1,fossilData1,true);

    if(xNum > 30)
    {
        customPlot->xAxis->setRange(xNum-29.5,xNum+0.5);
    }

    customPlot->replot(QCustomPlot::rpQueuedReplot);
}

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type() == QEvent::MouseButtonDblClick)   //双击图表事件
    {
        if(watched == ui->customplot)
        {
            qDebug()<<"customplot doubleClicked";
        }
        else if(watched == ui->customplot_2)
        {
            qDebug()<<"customplot_2 doubleClicked";
        }
    }
    return QWidget::eventFilter(watched,event);
}

void Widget::on_pb_Start_clicked()
{
    //maxLabel[0]->setText("-1.11");
    //minLabel[0]->setText("-1.11");
    maxLabel[0]->setText(QString::number(maxNum,'f',2));
    minLabel[0]->setText(QString::number(minNum,'f',2));
    maxLabel[1]->setText(QString::number(maxNum,'f',2));
    minLabel[1]->setText(QString::number(minNum,'f',2));

    serialNum ++;
    qDebug()<<"serialNum:"<<serialNum;
    xNum = serialNum - 0.5;
    if(yNum < 1.5)
    {
        yNum += 0.1;
    }
    else
    {
        yNum = -1.5;
    }
    qDebug()<<"xNum:"<<xNum<<"   yNum:"<<yNum;

    setBarReplot(m_customPlot);
    setBarReplot(m_customPlot_2);
}

void Widget::on_pb_Replot_clicked()
{
    //清除数据
    serialNum = 0;
    maxNum = 0;
    minNum = 0;
    xNum = 0;
    yNum = 0;
    maxLabel[0]->setText("   ");
    minLabel[0]->setText("   ");
    maxLabel[1]->setText("   ");
    minLabel[1]->setText("   ");
    m_customPlot->xAxis->setRange(0,30);
    m_customPlot->clearPlottables();
    m_customPlot->replot(QCustomPlot::rpQueuedReplot);
    m_customPlot_2->xAxis->setRange(0,30);
    m_customPlot_2->clearPlottables();
    m_customPlot_2->replot(QCustomPlot::rpQueuedReplot);
}

void Widget::on_pb_Change_clicked()
{
    //设置文本框
    maxNum = 1.00;
    minNum = -1.00;
    maxLabel[0]->setText(QString::number(maxNum,'f',2));
    minLabel[0]->setText(QString::number(minNum,'f',2));
    maxLabel[1]->setText(QString::number(maxNum,'f',2));
    minLabel[1]->setText(QString::number(minNum,'f',2));
    m_customPlot->replot(QCustomPlot::rpQueuedReplot);
    m_customPlot_2->replot(QCustomPlot::rpQueuedReplot);
}

3.widget.ui见上文。


三、下载链接

我的示例百度网盘链接:https://pan.baidu.com/s/1IAHCmKt4x14oef_09kD0Gg
提取码:xxcj

总结

测试发现多个QCustomPlot同时显示也是很流畅的,不会造成界面卡顿啥的,文中实现界面动态显示的关键是这句代码customPlot->xAxis->setRange(xNum-29.5,xNum+0.5),大家可以根据实际进行图表X轴范围的修改。在实际工作中可能还会遇到点击QCustomPlot界面来实现其他的功能,这时候可以考虑使用事件过滤器的方法,文中进行了双击图表的事件重写,可以根据项目需要进行更改。

本系列文章上一篇:(三)Qt+QCustomPlot生成上下方向/不同颜色的条形图(柱形图)

hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/17371.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构与算法】递归全流程详细剖析 | 详解图的深度优先遍历

&#x1f680; 作者 &#xff1a;“大数据小禅” &#x1f680;文章简介&#xff1a;本篇文章属于数据结构与算法系列文章&#xff0c;这篇文章会对算法中的递归进行一个详细的介绍&#xff0c;不仅是概念&#xff0c;而是从运行过程中的每一步进行详细分析。并使用递归的方式来…

Vue3 - 使用 mitt.js 进行组件通信(兄弟关系)

前言 在 Vue2 中&#xff0c;两个同级&#xff08;兄弟关系&#xff09;的组件传递数据&#xff0c;都是利用一个叫 EventBus 事件总线&#xff0c;利用这根总线&#xff0c;可以让两个毫无关系的组件进行通信。 其实这个问题的本质核心解决方案&#xff0c;就一句话。通过第三…

开传奇需要什么技术要什么条件

开传奇需要什么技术要什么条件 对于这个问题&#xff0c;近期问的人比较多。这也是热爱传奇这个游戏的朋友会问到的一个问题&#xff0c;因为喜欢玩这个游戏&#xff0c;也想要自己去开一个经营一个 不管是电脑端还是手机端。但是对于一些新手确实不知道该如何开始操作从哪些方…

基于PHP+MySQL的校园二手旧书回收捐赠系统

校园内因为所教授的课程比较多,人数基数也比较大,所以每年都会产生大量的二手废旧图书,很多时候这些图书还可以进行二次利用,如果直接当废品进行回收很暴殄天物的,所以为了能够让这些校园内的二手图书得到更多的利用,我们开发了PHP校园二手旧书回收捐赠系统 本系统分为前台和后…

「Redis数据结构」压缩列表(ZipList)

「Redis数据结构」压缩列表&#xff08;ZipList&#xff09; 文章目录「Redis数据结构」压缩列表&#xff08;ZipList&#xff09;一、概述二、结构三、连锁更新问题四、压缩列表的缺陷五、小结参考ZipList 是一种特殊的“双端链表” &#xff0c;由一系列特殊编码的连续内存块…

基于协同过滤进行金融产品个性化推荐 代码+数据

1.案例简介 (1)方法概述: 本教程包含如下内容: 从原始的数据文件中加载数据,进行训练集和测试集的切分。 对数据分batch, 利用用户侧信息,和商品侧信息,进行双塔模型的训练 结果展示 (2)宏观流程图 (3)案例知识点 pytorch 视频CTR预估指标 博客point wise 以及 pair wise …

从0到1图文教你如何将spring boot项目部署到minikube中去

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 源码 本项目博文的源码已上传github&#xff0c;有需要自取 github: https://github.com/weihubeats/weihubeats_demos/tree/master/spring-boot-demos/spring-…

C#界面里Control.Enabled 属性的使用

C#界面里Control.Enabled 属性的使用 在开发中即使一个细节也可以决定成败。 前段时间刚好是毕业季,公司招聘了很多应界毕业生, 由于项目非常多,许多老手都已经分配到各个项目上去,还有一些小项目不得不让这些新生力军来接手。 这些初生牛犊不怕虎,天天加班,夜夜苦战…

idea打开之前的项目不能正常编译/idea中项目Compile output丢失问题

报错笔记 文章目录错误一&#xff1a;Cannot resolve class or package java错误二&#xff1a;Compile output丢失问题下面的报错发生情况都是打开之前写的JavaWeb文件时&#xff0c;各个文件中的代码爆红错误一&#xff1a;Cannot resolve class or package ‘java’ 在idea…

【安卓应用渗透】第一篇:安卓逆向回顾和梳理-2211

文章目录安卓开发课程回顾第一课&#xff1a;安卓项目文件结构&#xff08;逻辑视图&#xff09;第五课&#xff1a;文件读取和数据库存取文件存取SQLite数据库存取安卓开发&#xff1a;案前资料库安卓逆向课程回顾第一课&#xff1a;基础逆向工具&#xff08;Apktool, Keytool…

【分享】订阅金蝶云进销存集简云连接器同步销货数据至金蝶云进销存系统

方案场景 在企业规模不断壮大的过程中&#xff0c;企业都是在钉钉内提交OA审批&#xff0c;并通过人工的方式统计多种审批数据&#xff0c;然后手动导入到某系统内&#xff0c;如果中间有调整又需要从头再进行核对&#xff0c;繁琐的流程严重影响了业务拓展。基于该方式企业希…

[附源码]SSM计算机毕业设计重庆工程学院教师宿舍管理系统论文JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Eolink征文活动--推荐国产神器Eolink!API优先,Eolink领先!

前言&#xff1a; 在我们后端开发者做项目的时候&#xff0c;避免不了与前端界面的交互&#xff0c;对于我来讲&#xff0c;在做项目的时候用到过postman&#xff0c;swagger做接口测试工作&#xff0c;在公司的时候公司主要用YApi可视化接口平台&#xff0c;最近使用了一个爆款…

负担过重何以轻装前行

随波逐流并不一定过得容易。 猜测负担过重原因&#xff1a; 所作的事情和预期差异大自己并不擅长目前所从事的专业恐惧失败试错成本过高基础薄弱无法持续成长简单问题复杂化复杂问题简单化…… 如何改变这种情况&#xff1f; 自我认知和外部感知都存在分析错位和信息不对称的…

解决ggplot绘制散点图形状超过6个的警告

正常画图&#xff1a; library(ggplot2) ggplot(mpg,aes(displ,hwy))geom_point(aes(shapeclass,colorclass))可以看出形状少了一个&#xff0c;SUV没有形状 并且还会弹出这样的警告&#xff1a; Warning message: “The shape palette can deal with a maximum of 6 discrete…

【附源码】Python计算机毕业设计网络求职招聘系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

更灵活定位内存地址的方法

更灵活定位内存地址的方法 文章目录更灵活定位内存地址的方法1.and和or2.以字符形式给出的数据3.[bxidata]4.SI、DI与寻址方式的灵活应用1.and和or and指令&#xff1a;逻辑与指令&#xff0c;按位进行与运算(同真为真) 比如&#xff1a; mov al, 01100011B and al, 00111011B …

速锐得适配进口福特烈马BRONCO车载 CAN总线应用随动转向大灯改装

适配进口福特烈马BRONCO车载 CAN总线应用随动转向大灯改装&#xff0c;必须先获得福特烈马BRONCO的原厂电路图纸&#xff0c;为此&#xff0c;速锐得准备了福特诊断仪、福特烈马BRONCO原厂电路图纸工具&#xff0c;适配装置、CAN数据采集设备、软件及线缆等一系列工具。 我们首…

【附源码】Python计算机毕业设计石家庄学院跳蚤市场

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[数据结构]二叉树的链式结构

作者&#xff1a; 华丞臧专栏&#xff1a;【数据结构】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。推荐一款刷题网站 &#x1f449; LeetCode刷题网站 目录 前言 一、二叉树的链式结构 二…