QT Creator上位机画波形之Qcharts使用学习

news2024/12/23 10:24:55

先看一个Qcharts的简单demo

Qcharts是QT自带的组件,不需要另外添加文件。

打开QT Creator,新建一个工程,命名可以参考下图:

在这里插入图片描述

基类选择QWidget:

在这里插入图片描述

.pro文件中添加charts模块
在这里插入图片描述

main.cpp源码:

#include "widget.h"

#include <QApplication>

// 包含line chart需要的头文件
#include <QChartView>
#include <QLineSeries>

// 引用命名空间
QT_CHARTS_USE_NAMESPACE

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //绘制折线图采用的是QLineSeries序列类,两点间只是简单的用直线连接。
    QLineSeries *series = new QLineSeries();
    
    // 添加实验数据,可以用 append 方法 或者  << 操作符
    series->append(0,2);
    series->append(QPointF(2,6));
    series->append(3,8);
    series->append(7,9);
    series->append(11,3);

    *series << QPointF(11,2) << QPointF(15,5) << QPointF(18,4) << QPointF(19,2);
    
    QChart *chart = new QChart();
    // 将图例隐藏
    chart->legend()->hide();
    // 关联series,这一步很重要,必须要将series关联到QChart才能将数据渲染出来:
    chart->addSeries(series);
    // 开启OpenGL,QLineSeries支持GPU绘制,Qt其他有的图表类型是不支持的。
    series->setUseOpenGL(true);
    // 创建默认的坐标系(笛卡尔坐标)
    chart->createDefaultAxes();
    // 设置图表标题
    chart->setTitle(QStringLiteral("Qt line chart example"));

    QChartView *view = new QChartView(chart);
    // 开启抗锯齿,让显示效果更好
    view->setRenderHint(QPainter::Antialiasing);
    view->resize(400,300);
    // 显示图表
    view->show();

    return a.exec();
}

运行效果:
在这里插入图片描述

上面是一个折线图的示例。
QLineSeries类以折线图的形式显示数据。
折线图用于将信息显示为由直线连接的一系列数据点。
基本的创建折线的步骤如下:

// 逐一添加数据点
QLineSeries* series = new QLineSeries();
series->append(0, 6);
series->append(2, 4);
...
chart->addSeries(series);

先new一个QLineSeries,再逐一添加数据点,最后把实例化的QLineSeries与chart关联起来
我们可以把series单独看成一条图线,chart看成一个画布或坐标系,两个组合起来才是完整的图形。

注意append是逐一往后添加数据点,就是说存在添加的先后顺序。

上面的demo程序中出现了三个重要的class,分别是QLineSeries,QChart,QChartView
QChartView是一个独立的小部件,可以显示图表。
QLineSeries类以折线图的形式显示数据。折线图用于将信息显示为由直线连接的一系列数据点。
QChart类管理图表系列、图例和轴的图形表示。 为了简单地在布局中显示图表,可以使用类QChartView来代替QChart。

折线用QLineSeries,曲线用QSplineSeries
QSplineSeries是用来绘制光滑曲线的类,它在两点之间连线时采用插值算法(插值就是通过一系列已知的数据点,来"猜测"未知点),绘制折线图采用的是QLineSeries序列类,两点间只是简单的用直线连接。
上面的示例我们改一下
QLineSeries *series = new QLineSeries();改成QSplineSeries *series = new QSplineSeries();
新增头文件#include <QSplineSeries>
运行效果:
在这里插入图片描述

动态刷新随机点

上节是直接在程序中用QChartView显示chart
这节看怎么在ui设计界面添加QChartView

找到Widget部件拉过去,调整好大小
在这里插入图片描述添加的Widget控件不能显示chart图表,需要将其提升为QchartView。
具体操作:拖一个Widget控件到界面,右键Widget->提升为, 在提升的类名称一栏填:QChartView,头文件可以不管,会自动生成(如下图),然后点添加再点提升。
在这里插入图片描述

在这里插入图片描述

.pro文件中添加charts模块
在这里插入图片描述

widget.h文件中需要添加using namespace QtCharts;或者QT_CHARTS_USE_NAMESPACE都可以

widget.h文件源码:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QtCharts/QSplineSeries>
#include <QtCharts>
#include <QDateTime>
using namespace QtCharts;
// 引用命名空间
//QT_CHARTS_USE_NAMESPACE

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    //声明QChart的实例,QSplineSeries的实例
    QChart *chart;   //画布
    QSplineSeries *series1; //线
    QDateTimeAxis *axisX;   //轴
    QValueAxis *axisY;
    QTimer *timer;    //计时器
    void drawLine();

    void initChart();
public slots:
    //声明timer的槽函数
    void timerDeal();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

main.cpp维持默认

#include "widget.h"

#include <QApplication>


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

widget.cpp源码:

#include "widget.h"
#include "ui_widget.h"
// 包含line chart需要的头文件
//#include <QChartView>
//#include <QLineSeries>
//#include <QSplineSeries>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //初始化QChart

    initChart();

    //设置timer
    timer = new QTimer();//创建定时器

    timer->setInterval(400);//设置定时周期

    connect(timer,SIGNAL(timeout()),this,SLOT(timerDeal()));//连接定时器与定时溢出处理槽函数

    timer->start();

}

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

//实现QChart的初始化函数

void Widget::initChart()
{
    chart = new QChart();//初始化QChart的实例

    series1 = new QSplineSeries();//初始化QSplineSeries的实例

    axisX = new QDateTimeAxis();//初始化X轴、Y轴

    axisY = new QValueAxis();

    //设置曲线的名称
    series1->setName("series1");

    chart->legend()->hide();//隐藏图例
    //把曲线添加到QChart的实例chart中
    chart->addSeries(series1);

    //设置X轴显示的范围
    axisX->setMin(QDateTime::currentDateTime().addSecs(-60*1));
    axisX->setMax(QDateTime::currentDateTime().addSecs(0));

    axisX->setFormat("hh:mm:ss");    //设置时间显示格式

    axisY->setMin(0); //设置Y轴范围
    axisY->setMax(10);
    //axisY->setRange(0,100); //也可以用这个设置范围
    
    //设置坐标轴上的格点
    axisX->setTickCount(5);
    axisY->setTickCount(10);

    //设置坐标轴显示的名称
    axisX->setTitleText("X轴");
    axisY->setTitleText("Y轴");

    //设置坐标轴的颜色,粗细,设置网格不显示
    axisY->setLinePenColor(QColor(Qt::darkBlue));
    axisY->setGridLineColor(QColor(Qt::darkBlue));
    axisY->setGridLineVisible(false);

    QPen penY1(Qt::darkBlue,3,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin);
    axisY->setLinePen(penY1);

    //把坐标轴添加到chart中,
    //addAxis函数的第二个参数是设置坐标轴的位置,
    //只有四个选项,下方:Qt::AlignBottom,左边:Qt::AlignLeft,右边:Qt::AlignRight,上方:Qt::AlignTop
    chart->addAxis(axisX,Qt::AlignBottom);
    chart->addAxis(axisY,Qt::AlignLeft);

    //把曲线关联到坐标轴
    series1->attachAxis(axisX);
    series1->attachAxis(axisY);

    //把chart显示到窗口上
    ui->widget->setChart(chart);
    ui->widget->setRenderHint(QPainter::Antialiasing);   //设置抗锯齿
}

//实现画线函数,动态更新
void Widget::drawLine()
{
    //每增加一个点改变X轴的范围,实现曲线的动态更新效果
    QDateTime bjtime=QDateTime::currentDateTime();

    chart->axisX()->setMin(QDateTime::currentDateTime().addSecs(-60*1));//系统当前时间的前一秒

    chart->axisX()->setMax(QDateTime::currentDateTime().addSecs(0));//系统当前时间

    //当曲线上最早的点超出X轴的范围时,剔除最早的点,
//    if(series1->count()>119)
//    {
//        series1->removePoints(0,series1->count()-119);
//    }
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));//设置种子
    int Y1=qrand()%9;//随机生成0到9的随机数
    //增加新的点到曲线末端
    series1->append(bjtime.toMSecsSinceEpoch(),Y1);
}

//实现timer的槽函数
void Widget::timerDeal()
{
    //定时画曲线
    drawLine();
}

效果:
在这里插入图片描述

对上面的例程我们需要了解的:
1、代码中没有定义chart 的整个图占的大小,所以ui里添加的Widget控件可以直接通过拉动四个角调整大小。
比如下图,就是只在ui里调整了Widget控件使其高度缩小的效果
在这里插入图片描述
2、对比一下不开抗锯齿的情况:
ui->widget->setRenderHint(QPainter::Antialiasing); 这句去掉
在这里插入图片描述
3、为了显示图表,除了Widget控件可以提升为QchartView,还有Graphics View组件也可以提升为QchartView(目前只测试了这两个可以提升QchartView,应该还有别的)

在这里插入图片描述
在这里插入图片描述

相关方法

QChart类方法

// 1.添加自定义坐标轴        Qt::AlignLeft 左侧X轴    Qt::AlignBottom 下端Y轴
void addAxis(QAbstractAxis *axis, Qt::Alignment alignment)    
// 2.设置默认坐标轴(QChart为根据系列上的数据,创建合适的坐标轴,数据中最小/最大的x值为坐标的x的范围,数据中最小/最大的y值为坐标的y的范围)
void createDefaultAxes()
// 3.移除坐标轴
void removeAxis(QAbstractAxis *axis)    
// 3.添加单个系列
void addSeries(QAbstractSeries *series)    
// 4.移除单个系列
void QChart::removeSeries(QAbstractSeries *series)
// 5.移除全部系列
void QChart::removeAllSeries() 
// 6.平移
void scroll(qreal dx, qreal dy)
// 7.设置外边距,通过设置负数可以是图表外面的空白减小   QMargins m(-10,-10,-10,-10);
void setMargins(const QMargins &margins)
// 8.设置图表绘制的位置,注意:不包含坐标轴     QRectF r(0,0,600,400);   此时将看不到Y轴坐标轴
void setPlotArea(const QRectF &rect)
// 9.设置标题
void setTitle(const QString &title)
// 9.1设置绘制标题的画刷
void setTitleBrush(const QBrush &brush)
// 9.2设置标题的字体 
void setTitleFont(const QFont &font)
// 10.放大/缩小坐标轴的范围   以图表的中心点开始放大/缩小
void zoom(qreal factor)
// 11.获取图表的图例,即系列的名称    通过 QLegend.hide() 可隐藏图表中所有的图例   
QLegend *QChart::legend() const       

QValueAxis类方法

// 1 设置范围
void setRange(qreal min, qreal max)
void setMax(qreal max)
void setMin(qreal min)    
// 2 设置网格划分类型      QValueAxis::TicksDynamic 按固定值划分  QValueAxis::TicksFixed  按份来划分(默认)
void setTickType(QValueAxis::TickType type); 
// 3 设置主要刻线线  设置为11,则按范围等分为10份, 在 QValueAxis::TicksFixed 时生效
void setTickCount(int count)
// 4 设置次要刻线, 设置为6,即给每个主刻度线在等分为5份  共 10 * 5 50份   在 QValueAxis::TicksFixed 时生效
void setMinorTickCount(int count)
// 5 按值设置刻度线,每两条刻度线间隔的值为设置的值,在 QValueAxis::TicksDynamic 时生效
void setTickInterval(qreal insterval)   
// 6 隐藏刻度线 
void QAbstractAxis::hide()    
// 7 设置主要刻度线的颜色
void setGridLineColor(const QColor &color)
// 8 设置主要刻度线的画笔
void setGridLinePen(const QPen &pen)
// 9 设置主要刻度线的可见性
void setGridLineVisible(bool visible = true)
// 10 设置轴线的颜色
void setLinePenColor(QColor color)
// 11 设置轴线的可见性
void setLineVisible(bool visible = true)
// 12 设置标题
void setTitleText(const QString &title)
void setTitleFont(const QFont &font)
void setShadesColor(QColor color)
void setShadesPen(const QPen &pen)
void setShadesBrush(const QBrush &brush)
void setTitleVisible(bool visible = true)
// 13 设置标签
void setLabelsAngle(int angle)
void setLabelsColor(QColor color)
void setLabelsFont(const QFont &font)
void setLabelFormat(const QString &format)      // ("%d")  %d为十进制显示   

QAbstractSeries类下的QXYSeries方法

QAbstractSeries为系列的基类,其下又分为 QXYSeries类(折线图、样条曲线图、散点图的基类)、QPieSeries类(饼状图)、QAbstractBarSeries类(条状图)等
-QAbstractSeries
---QXYSeries
-----QLineSeries 折线图
-------QSplineSeries样条曲线图    // 相比较于QLineSeries,更加平滑,同时更加耗时,大概为2.5倍时间,不过总时间很小(10000个点0.3ms),基本可忽略    
-----ScatterSeries 散点图    
---QPieSeries
---QAbstractBarSeries    

方法:
// 1.1 添加单个数据 不推荐        
void append(qreal x, qreal y)
// 1.2 添加单个数据 不推荐        
void append(const QPointF &point)
// 1.3 添加多个数据 不推荐        
void append(const QList<QPointF> &points)
// 1.4 替换单个数据 不推荐   
void replace(qreal oldX, qreal oldY, qreal newX, qreal newY)
// 1.5 替换多个数据 不推荐     
void replace(QList<QPointF> points)
// ***1.6 替换多个数据 极力推荐     (使用replace时,将不需要使用clear())
void replace(QVector<QPointF> points)
// 2 在系列中根据索引获取坐标
const QPointF &at(int index) const
// 3 插入某个点   
void insert(int index, const QPointF &point)
// 4 获取画刷 
QBrush brush() const
// 5 清空
void clear()
// 6 获取颜色   折线图、样条曲线图的线条颜色  散点图的填充颜色
virtual QColor color() const
// 7 获取点的数量
int count() const
// 8 获取绘制轮廓的笔
QPen pen() const
// 9 获取所有点
QVector<QPointF> pointsVector() const
// 10 该系列点是否绘制(是否可见)   注意:设置为false时,看不见凸出的点,但是线仍然可以看见
bool pointsVisible() const
// 11 设置绘制点的画刷
virtual void setBrush(const QBrush &brush)
// 12 设置绘制点的笔
virtual void setPen(const QPen &pen)    
// 13 设置绘制线的画刷  折线图、样条曲线图的线条颜色  散点图的填充颜色
virtual void setColor(const QColor &color)
// 14.1 设置点的标签,每个点都会被设置
void setPointLabelsFormat(const QString &format)
// 14.2 设置裁剪,超过图表区域部分会被裁剪
void setPointLabelsClipping(bool enabled = true)
// 14.3 设置点的标签的颜色
void setPointLabelsColor(const QColor &color)
// 14.4 设置点的标签的字体
void setPointLabelsFont(const QFont &font)
// 14.5 设置点的标签的可见
void setPointLabelsVisible(bool visible = true)
// 15 绑定坐标轴  需要连续绑定X轴、Y轴,而且要与QChart绑定同一组坐标轴
bool QAbstractSeries::attachAxis(QAbstractAxis *axis)  

小提示:对于代码中不清楚的类或方法,都可以选定后按F1进入帮助文档查看

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

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

相关文章

Nginx配置块location及rewrite详解

目录 一、location配置块详解 1.location 大致分为三类 2.location 常用的匹配规则 3.location 匹配的优先级 4.location 匹配流程 5.location 的实际使用 二、if 模块常用的nginx全局变量 三、rewrite详解 1.rewrite简介 2.rewrite实现跳转原理 3.rewrite 执行顺序 …

房企如何向制造业学习,提高运营效率,降本增效?

导语 | 近年来&#xff0c;随着外部环境的变化&#xff0c;国内的房地产市场受到了很大的冲击&#xff0c;也发生了显著的变化。很多人都认为房地产行业已经迎来了「青铜时代」甚至是「黑铁时代」&#xff0c;已由过去的「高杠杆、高增长、高利润」经营模式转变为「低利润、低增…

借助 VMware 技术加快数字化优先、客户至上的银行业的发展

迎接下一波客户至上的银行业创新浪潮 金融服务业对颠覆并不陌生。对于许多机构来说&#xff0c;新冠疫情的突然爆发&#xff0c;戏剧性地证明了运营敏捷性的价值。这些机构不仅加倍重视数字化体验&#xff0c;而且迅速适应了新情况&#xff1a;打破障碍&#xff0c;采用新技术…

【数据结构OJ题】链表带环问题

目录 1.判断链表是否带环 证明 2.寻找环的入口点 1.判断链表是否带环 原题链接&#xff1a;力扣 思路一&#xff1a;先遍历一遍链表&#xff0c;计算出链表的长度&#xff0c;然后将长度除二&#xff0c;在遍历半个链表即可。但是这种方法效率比较低。 思路二&#xff1a;…

【软考网络管理员】2023年软考网管初级常见知识考点(30)-文件管理与传送控制

涉及知识点 文件管理的概念&#xff0c;绝对路径和相对路径&#xff0c;设备管理&#xff0c;IO控制方式有哪些。 软考网络管理员常考知识点&#xff0c;软考网络管理员网络安全&#xff0c;网络管理员考点汇总。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》&#xff0c;更…

天天做Web测试,咋还不知道怎么测试呢?

目录 前言&#xff1a; 一、UI测试 二、链接测试 三、搜索测试 四、表单提交测试 五、输入域测试 六、分页测试 七、兼容性测试 前言&#xff1a; Web测试是一个比较广泛的测试领域&#xff0c;涵盖的测试内容较多&#xff0c;包括功能测试、性能测试、安全测试等。 下面就说一…

Docker 新手向导

博文目录 文章目录 新手向导 (Get Started)应用程序容器化下载应用代码容器化该应用配置镜像加速器 启动这个应用容器 更新应用程序共享应用程序推送镜像Play with Docker使用镜像 持久化数据库容器的文件系统容器卷 (Container volumes)保留所有数据深入卷 使用绑定装载快速卷…

Android Jetpack Compose之TabRow的使用

Android Jetpack Compose是一个现代化的UI工具包&#xff0c;它让开发者可以以声明式的方式来构建出美观且功能强大的Android应用。在本文中&#xff0c;我们将详细介绍其中的一个重要组件——TabRow。 一. TabRow简介 TabRow是Jetpack Compose中的一个组件&#xff0c;主要用…

在家用电脑怎么赚钱,在家就能获得收益的三种方式

如何在家赚钱可能是许多人都困扰的问题之一。实际上&#xff0c;有很多在家赚钱的方法可供选择。然而&#xff0c;我在网上发现许多人缺乏学习的动力&#xff0c;不愿意承担风险&#xff0c;因此大约80%的人选择从事辛苦劳动或成为被剥削的人&#xff0c;导致他们连续几年在互联…

SpringBoot中的bean管理

一、获取bean 默认情况下&#xff0c;Spring项目启动时&#xff0c;会把bean都创建好放在IOC容器中&#xff0c;如果想要主动获取这些bean&#xff0c;可以通过如下方式: 根据name获取bean: object getBean (String name)根据类型获取bean: <T> T getBean (Class<…

8.1 PowerBI系列之DAX函数专题-进阶-解决列排序对计算的影响

需求 下列矩阵中&#xff0c;在月份列不按照原始数据的month_no排列时&#xff0c;能正确计算销售额占比&#xff0c;但是当月份按照month_no排序时就会出错&#xff0c;需要解决这个问题。 实现 month % divide([amount],calculate([amount],all(date[month desc]))) //排…

计算机网络—局域网

文章目录 ARP协议以太网以太网帧结构交换机交换机的端口划分 PPP协议 MAC地址 封装在链路帧中的地址&#xff0c;作为每一个接口的地址。&#xff08;一般是48bit大小&#xff09; MAC地址是刻画到我们物理接口上的&#xff0c;我们的网卡一旦出厂之后就会携带一个唯一的物理地…

升级HarmonyOS 3,通话一步切换更便捷

小伙伴们&#xff0c;今天和大家来聊聊HarmonyOS 3音频播控中心有哪些真香体验。不少朋友可能会脱口而出&#xff1a;一键切换音频App&#xff0c;一键实现音频跨设备流转&#xff0c;还有音频共享。这一次&#xff0c;音频播控中心又带来了新技能——一键切换通话音频。 相信大…

Java集合相关问题

java集合框架体系 数据结构 算法复杂度分析 时间复杂度分析&#xff1a;对代码运行时间所消耗时间多少进行分析空间复杂度分析&#xff1a;对代码运行所占用的内存的大小进行分析 时间复杂度 时间复杂度分析&#xff1a;来评估代码的执行耗时 假如执行每行代码的执行耗时一…

electron实现子窗口中创建右键菜单

后续可能会用electron开发一些工具&#xff0c;包括不限于快速生成个人小程序、开发辅助学习的交互式软件、帮助运维同学一键部署的简易版CICD工具等等。 开发进度&#xff0c;取决于我懒惰的程度。 不过不嫌弃的同学还是可以先关注一波小程序&#xff0c;真的发布工具了&…

Shopee(虾皮)运营没流量?没销量?只因你没掌握店铺引流方法大全

一、站内引流 - 类目 选品&#xff1a;侧重高性价比的潮流商品&#xff0c;及时上架销售热卖商品&#xff1b; 根据目标客户群选品&#xff1a;比如&#xff0c;如果60%-70%的用户为年轻女性&#xff0c;则关注性价比高的潮流商品&#xff1b; 根据重点品类选品&#xff1a;流…

C语言笔记-小智课堂-常用语法

嵌入式常用C语言语法 - 小智课程 类型&字节转换 define语法 define只是单纯替换&#xff0c;如果是运算记得加括号 防止多个文件调用重定义问题 define与typedef&#xff08;替换与别名&#xff09; enum语法 enum用于变量的枚举。 定义枚举类型的变量&#xff0c;变量…

MSP430G2553 Proteus仿真0~5V电压表数码管显示报警系统-0046

MSP430G2553 Proteus仿真0~5V电压表数码管显示报警系统-0046 Proteus仿真小实验&#xff1a; MSP430G2553 Proteus仿真0~5V电压表数码管显示报警系统-0046 功能&#xff1a; 硬件组成&#xff1a;51单片机 8位数码管MAX7219数码管驱动模块多个按键LED灯蜂鸣器 1.准确测量信…

43 # buffer 的应用

buffer Buffer 代表的都是二进制数据&#xff0c;代表是内存&#xff0c;它不能扩容&#xff08;java 数组不能扩容&#xff0c;想扩容可以使用动态数组&#xff0c;或者生成一个新的内存拷贝过去&#xff09; 服务端可以操作二进制&#xff0c;Buffer 可以和字符串进行相互转…

学习adaboost(二,第一次迭代,c#实现)

我觉得这两个公式推导的特别好。我们来搞第一次迭代&#xff1a; 我们取x<2.5,标签1&#xff0c;else&#xff0c;标签-1这个分类器&#xff0c;发现分错的是5&#xff0c;7&#xff0c;8三组数据 &#xff0c;正确的都由0.1变为0.0714了&#xff0c;降低了&#xff0c;错误…