可视化开发:用Qt实现Excel级动态柱状图

Qt柱状图

QtChart

首先我们介绍一下 图表建立的基础:Qt Charts

QtChart 是Qt框架的一个模块,专注与提供交互式数据可视化功能

俗话就是 用于用户轻松创建各种类型的图表和图形界面

它包含的图表类型有很多:折线图,饼图,散点图,面积图等等,其中也包含我们这节重点要讲解的柱状图

知识点简介

QBarSet:用来存储柱状图中的一个数据集合。每个QBarSet代表一组柱子,每个柱子代表不同的颜色和标签

QBarSeries:同来管理多个QBarSet,将他们组成一个系列。负责处理柱子的布局和交互事件

QChart:图表的核心容器,负责管理所有的数据系列、坐标轴、图例、标题等。用来处理图表的整体样式,动画效果以及将数据渲染到视图

QChartView:用来显示QChart的视图组件,负责图表的可视化呈现

细节点

我们一般是将图标呈现在主控件,通过下面代码实现

this->setCentralWidget();

那么我们该如何 将图表加入到子控件中呢?

通过布局的方式 先创建一个新控件(Widget),之后向其中加入一个垂直布局(在ui中实现)

然后我们使用布局函数

newLayout->addwidget(图表);

这里大家知道方法就可以了,具体操作,下面我有具体的项目实例

实现步骤

先实现柱状图中的一组数据

最终成果展示

1、输入框输入数据,然后呈现在柱状图中

2、柱状图的纵坐标范围自动根据,输入数据的大小来进行改变

3、表格最多存储6个数据,内部可以修改(改变宏的值),但是有一个专门的容器去存储数据,但是现在缺少一个展示数据的框,大家可以用list widget来实现,这个操作较为简单,大家自行操作

4、加入了动态图表效果,这里不好展示,大家可以自己写一遍运行即可

头文件

项目所需要包含的头文件

#include <QMainWindow>

#include <QVector>

#include <QtCharts/QBarSet>

#include <QtCharts/QBarSeries>

#include <QtCharts/QChart>

#include <QtCharts/QChartView>

#include <QPushButton>

#include <QtCharts/QBarCategoryAxis>

#include <QtCharts/QValueAxis>

QBarSet

.h文件中,创建变量

QVector<int> dataEditEx1;

QVector<int> dataEdit1;

QVector<int> dataEditEx2;

QVector<int> dataEdit2;

QBarSet *setData1;

QBarSet *setData2;

dataEditEx 实现在图表中展现的数据,我们默认每组数据有

个柱子

dataEdit 用来每次输入的存储数据,让数据存储数量不在局限在6个

setData 柱状图的一组数据

补充

存储数据的方式:append() 或者 重载的<< 运算符

设置图标颜色 setColor()

我这里只提供 函数名 参数还有返回值大家自行利用 Qt Assistant查询即可,Qt内容较多,较杂,大部分东西都需要查,大家在学习工程中一定要学会查询!!

QBarSeries

用来管理多个 QBarSet 对象,定义 柱状图的显示方式

添加数据集(QBarSet)函数:append()

设置柱状宽度比例:setBarWidth() 参数范围0~1

QChart

图表的容器

添加数据集 addSeries()

设置标题 setTitle()

图表添加坐标轴

添加坐标轴的步骤

  1. 将坐标轴添加到图表(chart)中 addAxis
  2. 将坐标轴与数据集联系起来 attachAxis

QChartView

图表的展示

好了基础知识点大家都知道了,现在我给大家补充一些方法和小知识点

知识点与方法

1、补充一个遍历 数组和容器 的方式

for (元素类型 变量名 : 容器/数组)

{

// 循环体:每次迭代中,变量名会依次指向容器中的一个元素

}

这是一种 范围循环 ,其作用是 遍历容器或数组中的每一个元素

我们可以用这种方法 遍历容器数据或者 求容器中的最大值

2、更新图表的方式

先关掉数据集,再打开数据集即可

//更新表格

dataChart->removeSeries(dataSeries);

dataChart->addSeries(dataSeries);

项目实现

  1. 页面实现
ui页面
代码部分
.h文件
cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QVector>
#include <QtCharts/QBarSet>
#include <QtCharts/QBarSeries>
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QPushButton>
#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QValueAxis>
#include <QDebug>
using namespace QtCharts;
#define NUM 6

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void clearSet(QBarSet *setData);
public slots:
    void changeData();

private:
    Ui::MainWindow *ui;
    QVector<int> dataEditEx1;
    QVector<int> dataEdit1;
    QVector<int> dataEditEx2;
    QVector<int> dataEdit2;
    QStringList category;

    QBarSet *setData1;
    QBarSet *setData2;
    QBarSeries *dataSeries;
    QChart *dataChart;
    QChartView *dataView;
    QBarCategoryAxis *axisX;
    QValueAxis *axisY;
};

#endif // MAINWINDOW_H
知识点补充

再说mainwindow部分之前 我先说一下

坐标轴的添加步骤

分为x轴与y轴

x轴常作为 类别栏

y轴常作为 数值栏

类别栏的实现 有两个步骤

1、创建一个坐标轴

2、设置一个类别列表QStringList

    1. 为什么是列表呢,大家可以查一下 列表轴(QBarCategoryAxis)中的append 函数的参数要求

3、将列表添加到坐标轴中 append函数

数值栏的实现

  1. 创建一个数值轴
  2. 设置范围

数值栏和类别栏都需要的操作是把列表 把坐标轴添加到图表chart中,并于数据集series联系起来上面有讲

ui中按钮快捷键

mainwindow 函数部分
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //输入框1的呈现数据 默认6个0
    for(int i = 0;i < NUM;i++)
    {
        dataEditEx1.push_back(0);
    }

    //输入框2的呈现数据 默认6个0
    for(int i = 0;i < NUM;i++)
    {
        dataEditEx2.push_back(0);
    }

    //将数据输入数据表
    setData1 = new QBarSet("data1",this);
    for(QVector<int>::iterator it = dataEditEx1.begin();it != dataEditEx1.end();it++)
    {
        *setData1 << *it;
    }

    setData2 = new QBarSet("data2",this);
    for(QVector<int>::iterator it = dataEditEx2.begin();it != dataEditEx2.end();it++)
    {
        *setData2 << *it;
    }


    //设置颜色
    setData1->setColor(Qt::green);
    setData2->setColor(Qt::red);


    //将数据表打包
    dataSeries = new QBarSeries(this);
    dataSeries->append(setData1);
    dataSeries->append(setData2);


    //将数据包 生成图表

    dataChart = new QChart();
    dataChart->addSeries(dataSeries);
    dataChart->setTitle("数据呈现表格");


    //图表添加坐标轴
    QBarCategoryAxis *axisX = new QBarCategoryAxis();
    axisX->append(category);
    dataChart->addAxis(axisX,Qt::AlignBottom);
    dataSeries->attachAxis(axisX);

    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(0,1);
    dataChart->addAxis(axisY,Qt::AlignLeft);
    dataSeries->attachAxis(axisY);


    //将图表呈现出来
    dataView =new QChartView(dataChart,this);
    dataView->setRenderHint(QPainter::Antialiasing); // 抗锯齿
    ui->myWidgetVLayout->addWidget(dataView);

    connect(ui->subBtn,&QPushButton::clicked,this,&MainWindow::changeData);
}
按键函数实现
cpp 复制代码
//这个函数用来清空 数据表,我把它封装为了一个函数
void MainWindow::clearSet(QBarSet *setData)
{
    while(setData->count() > 0)
    {
        setData->remove(setData->count() - 1);
    }
}
void MainWindow::changeData()
{
    //清空数据表
    clearSet(setData1);
    clearSet(setData2);


    //处理显示容器
    dataEditEx1.remove(dataEditEx1.size() - 1);
    dataEditEx1.push_front(ui->data1Edit->text().toInt());
    dataEditEx2.remove(dataEditEx2.size() - 1);
    dataEditEx2.push_front(ui->data2Edit->text().toInt());


    //下面代码实现 坐标轴的值追随 展示数据的最大值
    //求出每个展示容器中的最大值
    int maxEx1 = 0,maxEx2 = 0;
    for(int &value : dataEditEx1)
    {
        maxEx1 = value < maxEx1 ? maxEx1 : value;
    }
    for(int &value : dataEditEx2)
    {
        maxEx2 = value < maxEx2 ? maxEx2 : value;
    }

    //重置数值坐标轴的范围
    axisY->setRange(0,(maxEx1 < maxEx2 ? maxEx2 : maxEx1));


    //数据输出到数据表
    for(QVector<int>::iterator it = dataEditEx1.begin();it != dataEditEx1.end();it++)
    {
        *setData1 << *it;
    }
    for(QVector<int>::iterator it = dataEditEx2.begin();it != dataEditEx2.end();it++)
    {
        *setData2 << *it;
    }


    //更新表格
    dataChart->removeSeries(dataSeries);
    dataChart->addSeries(dataSeries);


    //把数据同步到数据存储容器
    dataEdit1.push_back(ui->data1Edit->text().toInt());
    dataEdit2.push_back(ui->data2Edit->text().toInt());
}

结束

今天的分享到这里就结束了,如果你喜欢我的分享,请点赞收藏夹关注,谢谢大家

相关推荐
跟着珅聪学java2 小时前
spring boot +Elment UI 上传文件教程
java·spring boot·后端·ui·elementui·vue
強云2 小时前
界面架构- MVP(Qt)
qt·架构
我命由我123452 小时前
Spring Boot 自定义日志打印(日志级别、logback-spring.xml 文件、自定义日志打印解读)
java·开发语言·jvm·spring boot·spring·java-ee·logback
徐小黑ACG3 小时前
GO语言 使用protobuf
开发语言·后端·golang·protobuf
0白露4 小时前
Apifox Helper 与 Swagger3 区别
开发语言
Tanecious.5 小时前
机器视觉--python基础语法
开发语言·python
叠叠乐5 小时前
rust Send Sync 以及对象安全和对象不安全
开发语言·安全·rust
Tttian6226 小时前
Python办公自动化(3)对Excel的操作
开发语言·python·excel
Merokes7 小时前
关于Gstreamer+MPP硬件加速推流问题:视频输入video0被占用
c++·音视频·rk3588
独好紫罗兰7 小时前
洛谷题单2-P5713 【深基3.例5】洛谷团队系统-python-流程图重构
开发语言·python·算法