【Qt开发】QtCharts图表 在ui上添加QChartView控件并进行绘图配置
文章目录
为了使开发更方便 对使用到的模块进行了总结 最终封装成了一个类、函数库
使用typedef、class类、回调函数等来建立 方便打包和开发
开源地址:
gitee地址
【Qt开发】建立自己的Qt基本类、函数库封装 包括图表、多线程、串口等
后续更新以gitee为准
控件安装和模块导入
QChartView位于QtCharts模块下
在VS和Qt Creator上分别位于:
和
在资源模块管理中可以找到就表明安装了 否则就需要另外安装
在VS上 只需要像第一张图一样直接勾选即可
但在Qt Creator上开发时 需要在.pro文件中加入:
QT += charts
如:
导入后进行编译一遍
然后再在头文件中导入相应的库即可
#include<QChart>#include<QChartView>
导入后需要加入一行宏
QT_CHARTS_USE_NAMESPACE
或
usingnamespace QT_CHARTS_NAMESPACE;//等价于usingnamespace QtCharts
不然用不了库下面的控件
在ui上添加QChartView控件
ui上没有QChartView控件 所以只能用其他的控件来提升为QChartView
常用QWidget来进行提升(其他的控件也可以 比如Graphics View等 但还是推荐用QWidget 好处就是可以在这个上面再次放置一些按钮等控件 另外 如果涉及到新窗口显示图表 也得用这个)
右键选择得控件-提升为-输入QChartView 然后会自动链接到头文件 再点添加即可 我这里已经添加好了
添加好了以后 选中刚刚添加的东西 点击提升
勾不勾选全局包含都无所谓(推荐不勾)
提升后 在ui_mainwindow.h里面就会看到导入的库
全局包含和非全局包含的区别就是一个用<>一个用""导入
这在C/C++里面的区别就不多说了 后者优先从用户工程目录下搜素头文件 可以自己修改头文件等等 前者是系统目录
导入后 我们可以看到来自于系统目录(因为我们用户目录下没有)
如果你在mainwindow.h下面导入了ui_mainwindow.h
则在编译后 可以看到一堆报错
(如果没有 则不管有没有全局包含 都不会报错 但我还是推荐不要全局包含 请看下文)
(ui_mainwindow.h是在编译后生成的 Qt Creator的编译流程不太清楚 我是为了开发方便 才在mainwindow.h里面导入ui_mainwindow.h的 解决方案是直接不导入 或者按我下面的方法解决 也是无论有没有导入ui_mainwindow.h的最优解)
这其实就是因为在ui_mainwindow.h里面 我们没有调用
QT_CHARTS_USE_NAMESPACE
宏定义(先前我们是在mainwindow.h里面调用的)
而ui_mainwindow.h是在下面的头文件
解决方法就是在ui_mainwindow.h导入库和宏定义
但每次ui改变的时候 ui_mainwindow.h自动生成 就会覆盖我们修改的部分
还可以直接改qchartview.h文件 但作为系统的库 最好不改
所以我们可以复制一个qchartview.h文件到用户目录
然后在这里加上宏定义
这样就没有任何报错了
QChartView图表配置
我这里写了几个函数和结构体 用于一键配置
#ifndefMY_QT_DEF_H#defineMY_QT_DEF_H#include<QValueAxis>#include<QList>#include<QSplineSeries>#include<QString>#include<QChart>#include<QChartView>
QT_CHARTS_USE_NAMESPACE
typedefstruct{float min;float max;
QString tittle;
QString format;
Qt::Alignment alignment;
QValueAxis *axis;}MY_QChartView_Float_Axis_Struct;//splineSeries曲线实例化(折线用QLineSeries)typedefstruct{int maxSize;
QList<float> data;
QString tittle;
MY_QChartView_Float_Axis_Struct X;
MY_QChartView_Float_Axis_Struct Y;
QPainter::RenderHint renderHint;//上面是必配置的参数 下面是指针类型
QSplineSeries *splineSeries;
QChart *chart;
QChartView *chartView;}MY_QChartView_Float_Struct;voidInit_MY_QChartView_Float_Axis_Struct(MY_QChartView_Float_Axis_Struct *Stu,QChart *chart);voidInit_MY_QChartView_Float_Struct(MY_QChartView_Float_Struct *Stu);voidAdd_MY_QChartView_Float_Value(MY_QChartView_Float_Struct *Stu,float value);#endif// MY_QT_DEF_H
#include"MY_QT_DEF.h"voidInit_MY_QChartView_Float_Axis_Struct(MY_QChartView_Float_Axis_Struct *Stu,QChart *chart){
Stu->axis->setLabelFormat(Stu->format);
Stu->axis->setTitleText(Stu->tittle);
chart->addAxis(Stu->axis, Stu->alignment);
Stu->axis->setRange(Stu->min,Stu->max);}voidInit_MY_QChartView_Float_Struct(MY_QChartView_Float_Struct *Stu){
Stu->chart=newQChart();
Stu->splineSeries =newQSplineSeries();
Stu->X.axis=newQValueAxis();
Stu->Y.axis=newQValueAxis();
Stu->chart->legend()->hide();
Stu->chart->setTitle(Stu->tittle);
Stu->chart->addSeries(Stu->splineSeries);Init_MY_QChartView_Float_Axis_Struct(&Stu->X,Stu->chart);Init_MY_QChartView_Float_Axis_Struct(&Stu->Y,Stu->chart);
Stu->splineSeries->attachAxis(Stu->X.axis);
Stu->splineSeries->attachAxis(Stu->Y.axis);
Stu->chartView->setChart(Stu->chart);
Stu->chartView->setRenderHint(Stu->renderHint);}//添加数据自动移动函数voidAdd_MY_QChartView_Float_Value(MY_QChartView_Float_Struct *Stu,float value){
Stu->data.append(value);while(Stu->data.size()> Stu->maxSize){
Stu->data.removeFirst();}
Stu->splineSeries->clear();float xSpace =(Stu->X.max-Stu->X.min)/(Stu->maxSize -1);for(int i =0; i < Stu->data.size();++i){
Stu->splineSeries->append(xSpace * i, Stu->data.at(i));}}
调用方式:
QChartView_Float_Stu.chartView=this->ui->chartview;
QChartView_Float_Stu.maxSize=21;
QChartView_Float_Stu.renderHint=QPainter::Antialiasing;
QChartView_Float_Stu.tittle="曲线测试";
QChartView_Float_Stu.X.tittle="X";
QChartView_Float_Stu.X.min=0;
QChartView_Float_Stu.X.max=20;
QChartView_Float_Stu.X.format="%i";
QChartView_Float_Stu.X.alignment=Qt::AlignBottom;
QChartView_Float_Stu.Y.tittle="Y";
QChartView_Float_Stu.Y.min=0;
QChartView_Float_Stu.Y.max=100;
QChartView_Float_Stu.Y.format="%0.2f";
QChartView_Float_Stu.Y.alignment=Qt::AlignLeft;Init_MY_QChartView_Float_Struct(&QChartView_Float_Stu);
在定时器里面执行:
voidMainWindow::timerTimeOut(){int i =QDateTime::currentDateTime().toMSecsSinceEpoch()/1000%100;qDebug()<<"timer "<<i<<"\n";Add_MY_QChartView_Float_Value(&this->QChartView_Float_Stu,i);}
效果:
可以通过ui设计直接调整大小
附录:C语言到C++的入门知识点(主要适用于C语言精通到Qt的C++开发入门)
C语言与C++的不同
C语言是一门主要是面向工程的语言
C++则是面向对象
C语言中 某些功能实现起来较为繁琐
比如结构体定义:
一般写作:
typedefstructstu_A{}A;
也可以写作:
typedefstruct{}A;
但 大括号后面的名称是不可省去的
不过 C++的写法就比较简单
除了支持上述写法外
也支持直接声明
typedefstructA{}
另外 C++是完全支持C语言库和语法的
不过C++里面的库也有些很方便的高级功能用法 只不过实现起来可能不如C的速度快
再者 C语言与C++的编译流程不一样
C语言没有函数重载 所以给编译器传参就是直接传函数名称
但是C++除了传函数名称外 还会穿函数的参数、类型等等 以实现函数重载
C++中写C语言代码
上文提到 C++可以完全兼容C的写法
但是编译流程也还是不一样
所以如果在编译层面进行C语言代码编译 则通常用以下方法:
extern"C"{...}
表面大括号内的内容用C的方法进行编译
另外 如果还是用C++的编译器 但要实现C语言函数 则需要用到C语言的库
在C语言中 我们一般用如下方法导入库
#include<stdio.h>
此方法同样适用于C++ 但是C++可以更方便的写成去掉.h的方式
比如:
#include<iostream>
在C++中 为了调用C语言的库 可以采用在原库名称前加一个"c"的方式导入
如:
#include<cstdio>
这样就可以使用printf等函数了 甚至比C++的std方法更快
C语言到C++的知识点
Qt开发中需要了解的C++基础知识
namespace
C++面向对象的特性下诞生的一个名称
表示某个函数、变量在某个集合下 用作namespace
比如
<iostream>
库中的关键字cin在std下 则写作std::cin
std就是namespace
::表示某空间下的某某
前面是空间名称 后面是变量、函数名称
用
using namespace
可以告诉编译器以下都用xx名称空间
比如:
usingnamespace std;
cout<<"a";
如果没有告诉编译器所使用的空间名称 则要写成:
std::cout<<"a";
同样 可以自定义某一段代码属于哪个空间:
namespace xx
{...}
输入输出
在C++中 用iostream作为输入输出流的库
#include<iostream>
用cin和cout关键字进行输入和输出
如:
usingnamespace std;int a=0;
cin>>a;//输入到a
cout<<a;//输出a
类比scanf和printf
同样 还有一个关键字endl表示换行
cout和cin的传参是不固定的
由编译器自行裁定
字符串类型
在C语言中 常用char *表示字符串
但是在C++中 可以直接用string类型
比如:
char* s="456";
string str="123";
由于cout的特性 这两种字符串都可以直接打印
但如果使用C语言中printf的打印方式时 采用%s方式打印字符串 则不能传入string类型
class类
C++的核心就是class
同Python等支持面向对象的语言一样
可以理解成一个支持函数、继承、自动初始化、销毁的结构体
在class类中 有
private
私有、
public
公有变量
前者只能内部访问 后者可以外部调用使用
如:
classA{public:int a;private:int b;}
a可以用A.a的方式方位 b则外部无法访问
构造函数和析构函数(解析函数)
构造函数可以理解成对类的初始化 反之析构函数则是退出时进行销毁前的函数
两者需要与类的名称相同 析构函数则在前面加一个~表示非
如:
classA{public:int a;A();~A();private:int b;}A::A(){...}A::~A(){...}
构造函数可以定义传参 析构函数则不行
类的继承
如果有两个类A和B 想让A里面包含B 则可以写作继承的写法
继承后 A类的变量可以直接调用B下面的成员
如:
classB{int b;}classA:publicB{int a;}
在定义A后 可以访问到B的成员b 当然 继承也可以私有
版权归原作者 网易独家音乐人Mike Zhou 所有, 如有侵权,请联系我们删除。