QT自定义控件折线图、趋势图。

news2024/11/28 8:52:11

这里提供两种实现方式,一直自绘的自定义控件,一直三方SDK(qcustomplot)。
这里主要介绍自绘的,它的优点是结构简单,代码逻辑好修改,容易定制,缺点是功能相对单一。三方的qcustomplot优点是功能丰富,性能突出。缺点是代码结构复杂,难以根据实际需求快速定制。

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

方法一:
接口介绍:

//传入数据,根据实际情况添加。
struct ChartPointInfo
{
ChartPointInfo();
ChartPointInfo(double toilConspn,QColor tcolor,double tline_Wide = 1,quint64 txAxis = 0) {
oilConspn = toilConspn;color = tcolor;line_Wide = tline_Wide;xAxis = txAxis;
}
quint64 xAxis;
QColor color;
double line_Wide = 0;
};

void addPointInfo(ChartPointInfo ptinfo); //单个数据增加。
void setData(QList<ChartPointInfo> &datas); //批量数据整体赋值。

void setxAxisUnit(QString val); //设置x轴名称
void setyAxisUnit(QString val); //设置y轴名称
void setShowType(int num){m_showType = num;} //设置显示类型。0:显示规定长度的数据;1:显示所有数据。
void setChartType(int num){m_chartType = num;}//设置表的类型。0:柱状图;1:折线图。
void setChartModel(int num){m_chartModel = num;}//设置x轴单位模式。0:数值;1:时间。
void setxAxisRange(int min,int max){m_xAxisMin = min;m_xAxisMax = max;}//设置x轴范围
void setyAxisRange(int min,int max){m_yAxisMinVal = min;m_yAxisMaxVal = max;}//设置y轴范围

调用接口:

        MChartCurve* curveChart = new MChartCurve();
        curveChart->setFixedSize(500,300);
        curveChart->setxAxisUnit("TIME");
        curveChart->setyAxisUnit("(单位:L)");
        curveChart->setShowType(1);
        curveChart->setChartType(0);
        curveChart->setChartModel(0);

实现代码:
.h

#ifndef MCHARTCURVE_H
#define MCHARTCURVE_H

#include <QWidget>
#include <QPainter>

struct ChartPointInfo
{
    ChartPointInfo();
    ChartPointInfo(double toilConspn,QColor tcolor,double tline_Wide = 1,quint64 txAxis = 0)
    {
        oilConspn = toilConspn;color = tcolor;line_Wide = tline_Wide;xAxis = txAxis;
    }

    double oilConspn = 0.0;
    quint64 xAxis;
    QColor color;
    double line_Wide = 0;
};

class MChartCurve : public QWidget
{
    Q_OBJECT
public:
    MChartCurve(QWidget* parent = nullptr);
    ~MChartCurve();
    void addPointInfo(ChartPointInfo ptinfo);
    void setData(QList<ChartPointInfo> &datas);

    void setxAxisUnit(QString val);
    void setyAxisUnit(QString val);
    void setShowType(int num){m_showType = num;}
    void setChartType(int num){m_chartType = num;}
    void setChartModel(int num){m_chartModel = num;}
    void setxAxisRange(int min,int max){m_xAxisMin = min;m_xAxisMax = max;}
    void setyAxisRange(int min,int max){m_yAxisMinVal = min;m_yAxisMaxVal = max;}
protected:
    void paintEvent(QPaintEvent *event);
    void timerEvent(QTimerEvent *event);
private:
    QList<ChartPointInfo> m_chartPtInfos;
    double m_yAxisSize = 10;
    double m_yAxisMaxVal = 100;
    double m_yAxisMinVal = 0;
    double m_xAxisSize = 5;
    double m_xAxisMax = 10;
    double m_xAxisMin = 0;
    int m_showType = 1;
    int m_chartType = 0;
    int m_chartModel = 0;
    QString m_xAxisUnit;
    QString m_yAxisUnit;
    qint64 m_timeSpec = 0;

};

#endif // MCHARTCURVE_H

.cpp

#include "mchartcurve.h"
#include <QDateTime>
#include <QDebug>
#include <QApplication>

MChartCurve::MChartCurve(QWidget *parent) /*: QWidget(parent)*/
{
    //    this->setAttribute(Qt::WA_TranslucentBackground);
    startTimer(1000);
}

MChartCurve::~MChartCurve()
{

}

void MChartCurve::timerEvent(QTimerEvent *event)
{
    addPointInfo(ChartPointInfo(rand()%(int)m_yAxisMaxVal,QColor(rand()%255,rand()%255,rand()%255),0.5));
}

void MChartCurve::addPointInfo(ChartPointInfo ptinfo)
{
    static uint initTime = QDateTime::currentDateTime().toTime_t();

    //模拟数据
    ptinfo.xAxis = QDateTime::currentDateTime().toTime_t() - initTime;

    m_timeSpec = initTime;
    m_chartPtInfos.append(ptinfo);

    if (m_showType == 0)
    {
        if (m_chartPtInfos.size() > m_xAxisMax-m_xAxisMin + 1)
        {
            m_chartPtInfos.removeFirst();
            m_xAxisMin++;
            m_xAxisMax++;
        }
    }
    else
    {
        if (m_xAxisMax < ptinfo.xAxis)
            m_xAxisMax = m_xAxisMax*2;
    }
    update();
}

void MChartCurve::setData(QList<ChartPointInfo>& datas)
{
    m_chartPtInfos = datas;
    if (m_showType == 0)
    {
        if (m_chartPtInfos.size() > m_xAxisMax-m_xAxisMin + 1)
        {
            m_chartPtInfos.removeFirst();
            m_xAxisMin++;
            m_xAxisMax++;
        }
    }
    else
    {
        if (m_xAxisMax < datas.last().xAxis)
            m_xAxisMax = m_xAxisMax*2;
    }
    update();
}

void MChartCurve::paintEvent(QPaintEvent *event)
{
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing);
    QPen pen;
    QFont font;

    double xstartPos = 30;                 //x轴全局坐标起始点
    double ystartPos = 10;                 //y轴全局坐标起始点
    double xWidth = width() - 80;
    double yHeight = height() - 40;
    double yAxisSize = m_yAxisSize;        //x轴刻度数
    double yAxisMaxVal = m_yAxisMaxVal;
    double xAxisSize = m_xAxisSize;        //y轴刻度数
    double xAxisMax = m_xAxisMax;
    double xAxisMin = m_xAxisMin;

    //chart
    double xAxisTextLen = xWidth/(xAxisMax - xAxisMin);
    double yAxisTextLen = yHeight/yAxisMaxVal;
    for (int i = 0; i < m_chartPtInfos.size() - 1; i++)
    {
        ChartPointInfo startinfo = m_chartPtInfos[i];
        ChartPointInfo endinfo = m_chartPtInfos[i+1];
        pen.setWidthF(startinfo.line_Wide);
        pen.setColor(startinfo.color);
        p.setPen(pen);
        p.setBrush(QBrush(startinfo.color));

        if (m_chartType == 1)
            p.drawRect(QRectF(xstartPos + (startinfo.xAxis-xAxisMin)*xAxisTextLen,ystartPos + (yAxisMaxVal-startinfo.oilConspn)*yAxisTextLen,
                              qAbs(endinfo.xAxis - startinfo.xAxis)*xAxisTextLen,10 + yHeight - (ystartPos + (yAxisMaxVal-startinfo.oilConspn)*yAxisTextLen)));
        else
            p.drawLine(QPointF(xstartPos + (startinfo.xAxis-xAxisMin)*xAxisTextLen,ystartPos + (yAxisMaxVal-startinfo.oilConspn)*yAxisTextLen)
                       ,QPointF(xstartPos + (endinfo.xAxis-xAxisMin)*xAxisTextLen,ystartPos + (yAxisMaxVal-endinfo.oilConspn)*yAxisTextLen));

    }

    //base line
    double oilprec = 0.6;
    double baseyPos = yAxisMaxVal * (1 - oilprec) * yAxisTextLen;
    pen.setStyle(Qt::DashLine);
    pen.setColor(QColor("#df7050"));
    p.setPen(pen);
    p.drawLine(QPoint(xstartPos,10 + baseyPos),QPoint(xstartPos + xWidth,10 + baseyPos));

    pen.setStyle(Qt::SolidLine);
    pen.setColor(QColor("#000000"));
    p.setPen(pen);
    font.setPointSize(8);
    p.setFont(font);

    //xAxis
    p.drawLine(QPoint(xstartPos,ystartPos + yHeight),QPoint(xstartPos + xWidth,ystartPos + yHeight));
    //xAxis Unit
    p.drawText(xstartPos + xWidth + 10,yHeight,50,20,Qt::AlignLeft|Qt::AlignVCenter,m_xAxisUnit);
    //xAxis text
    for (int i = 0; i < xAxisSize + 1; i++)
    {
        p.drawLine(xstartPos+(xWidth/xAxisSize)*i,yHeight+10,xstartPos+(xWidth/xAxisSize)*i,yHeight+7);
        if (m_chartModel == 1)
        {
            int timespec = m_timeSpec + xAxisMin+(xAxisMax-xAxisMin)/xAxisSize*i;
            p.drawText(xstartPos+(xWidth/xAxisSize)*i-25,yHeight+10,50,20,Qt::AlignCenter,QDateTime::fromTime_t(timespec).toString("hh:MM:ss"));
        }
        else
            p.drawText(xstartPos+(xWidth/xAxisSize)*i-20,yHeight+10,40,20,Qt::AlignCenter,QString::number(xAxisMin+(xAxisMax-xAxisMin)/xAxisSize*i,'f',0));
    }

    //yAxis
    p.drawLine(QPoint(xstartPos,10),QPoint(xstartPos,ystartPos + yHeight));
    //yAxis Unit
    p.drawText(xstartPos + 5,0,60,20,Qt::AlignLeft|Qt::AlignVCenter,m_yAxisUnit);
    //yAxis text
    for (int i = 0; i < yAxisSize; i++)
    {
        p.drawLine(xstartPos,ystartPos+(yHeight/yAxisSize)*i,xstartPos + 3,ystartPos+(yHeight/yAxisSize)*i);
        p.drawText(0,ystartPos+(yHeight/yAxisSize)*i-10,xstartPos - 5,20,Qt::AlignRight|Qt::AlignVCenter,QString::number(yAxisMaxVal/yAxisSize*(yAxisSize-i)));
    }
}

void MChartCurve::setxAxisUnit(QString val)
{
    m_xAxisUnit = val;
}

void MChartCurve::setyAxisUnit(QString val)
{
    m_yAxisUnit = val;
}

方法二:使用qcustomplot实现
柱状图和折线图:
请添加图片描述
请添加图片描述

代码:
首先需要引入文件qcustomplot.h和qcustomplot.cpp
下载地址:https://download.csdn.net/download/weixin_43246170/87785302
.h

    QCustomPlot* m_cusPlot = nullptr;
    QCPBars *m_bars = nullptr;
    QVector<double> m_xList;
    QVector<double> m_yList;

.cpp

void SeaChartWidget::creatPlotChart()
{
    //qcomtomplot
    m_cusPlot = new QCustomPlot();
    m_cusPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
                               QCP::iSelectLegend | QCP::iSelectPlottables);
    m_cusPlot->axisRect()->setRangeDrag(Qt::Horizontal);
    m_cusPlot->setFixedSize(660,300);
    //背景透明
    m_cusPlot->setBackground(Qt::transparent);
    m_cusPlot->setStyleSheet("background:transparent");

    //        m_cusPlot->yAxis->setTickLabels(false); //关闭左侧y轴刻度值
    //        m_cusPlot->axisRect()->setupFullAxesBox(); //补全上下边框线

    //y
    m_cusPlot->xAxis->setRange(120, 120, Qt::AlignRight);
    m_cusPlot->yAxis->setRange(1000, 1000, Qt::AlignRight);
    m_cusPlot->yAxis->ticker()->setTickStepStrategy(QCPAxisTicker::TickStepStrategy::customTickCount);
    m_cusPlot->yAxis->ticker()->setTickCount(7);

    //x
    QSharedPointer<QCPAxisTickerDateTime> dateTick(new QCPAxisTickerDateTime);
    dateTick->setDateTimeFormat("hh:mm:ss");
    dateTick->setTickOrigin(6);    //设置第一个刻度值
    m_cusPlot->xAxis->setTicker(dateTick);
    m_cusPlot->xAxis->ticker()->setTickStepStrategy(QCPAxisTicker::TickStepStrategy::customTickCount);
    m_cusPlot->xAxis->ticker()->setTickCount(6);

#if 1 //柱状图
    m_bars = new QCPBars(m_cusPlot->xAxis, m_cusPlot->yAxis);  // 使用xAxis作为柱状图的x轴,yAxis作为y轴
    m_bars->setAntialiased(false); // 为了更好的边框效果,关闭抗齿锯
    m_bars->setPen(QPen(QColor(0, 160, 140).lighter(130))); // 设置柱状图的边框颜色
    m_bars->setBrush(QColor(20,68,106));  // 设置柱状图的画刷颜色

    //隐藏网格
    m_cusPlot->xAxis->grid()->setVisible(false);
    m_cusPlot->yAxis->grid()->setVisible(false);

    //坐标轴箭头
    m_cusPlot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
    m_cusPlot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
#endif

    //显示右侧y轴
    //        m_cusPlot->yAxis2->setVisible(true);
    //        m_cusPlot->axisRect()->axis(QCPAxis::atRight, 0)->setRange(1000, 1000, Qt::AlignRight);
    //        m_cusPlot->addGraph(m_cusPlot->xAxis, m_cusPlot->axisRect()->axis(QCPAxis::atRight, 0));
    m_cusPlot->addGraph(m_cusPlot->xAxis);

    m_cusPlot->graph(0)->setPen(QPen(Qt::blue));
    QGraphicsProxyWidget *w = m_mapView->scene()->addWidget(m_cusPlot);
    w->setPos(GraphicsMap::toScene(MyGeoCoordinate(m_lat,m_lon)));
}

void SeaChartWidget::updatePlotData()
{
    static double index = 0;
    index = index + 2;
    m_xList.append(index);
    m_yList.append(rand()%500);

#if 0 //折线图
    m_cusPlot->graph(0)->setData(m_xList, m_yList);//指定数据
    //        m_cusPlot->graph(0)->rescaleValueAxis(false,true);  //x,y刻度值根据数据实时变化
#else //柱状图
    m_bars->setData(m_xList, m_yList);
    //        m_bars->rescaleValueAxis(false,true);  //x,y刻度值根据数据实时变化
#endif
    //注意需要放在数据后面,否则会出现第一次设置未成功
    m_cusPlot->xAxis->rescale(true);   //true:从右侧开始绘制最新数据;false:从左侧开始绘制最新数据
    m_cusPlot->xAxis->setRange(m_cusPlot->xAxis->range().upper, 120, Qt::AlignRight);
    m_cusPlot->replot();
}

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

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

相关文章

循迹模块(应用于小车)

1.1循迹模块使用 TCRT5000传感器的红外发射二极管不断发射红外线 当发射出的红外线没有被反射回来或被反射回来但强度不够大时&#xff0c; 红外接收管一直处于关断状态&#xff0c;此时模块的输出端为高电平&#xff0c;指示二极管一直处于熄灭状态 被检测物体出现在检测范…

C++ | 数组拷贝

C | 数组拷贝 文章目录 C | 数组拷贝数组名数组拷贝1.对应位拷贝2.地址位移赋值3. memcpy内存拷贝4.字符数组拷贝 Reference 数组名 C数组间赋值不能直接通过数组名称 randy sesame进行&#xff0c;因为数组名并不是指针&#xff0c;大部分情况下&#xff0c;编译器会隐式转换…

使用nvm 管理node.js版本的安装过程

一个 nodejs 版本管理工具&#xff01;—— nvm 在项目开发过程中&#xff0c;随着框架的不断更新迭代&#xff0c;对一些环境依赖的版本也有影响&#xff0c;部分的老项目可能需要低版本的 node.js 才能正常使用&#xff0c;而后期新开发的项目可能需要更高的 node.js 版本才…

都说2023是测试员的危机年,却不断有人跳槽拿20K+,为什么?

从 2021 年上旬开始触发的经济危机逐渐蔓延到普通人的生活中&#xff0c;裁员、倒闭、跑路俨然已成为刷爆朋友圈的高频热词。随之而来的是一系列因舆论所牵动的各种焦虑感弥漫在人群中&#xff0c;无论是大公司还是之前处于风口浪尖的明星创业公司&#xff0c;几乎无一幸免。聊…

ANR实战案例3 - 应用在部分低端机ANR优化案例

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言一、Blocked状态1.案例一2.案例二3.案例三 二、高低端机区分1.WebView预加载 三、…

Flink基础介绍-2 架构

Flink基础介绍-1 概述 二、Flink架构2.1 Flink的设计架构2.2 Flink的运行架构2.3 Flink的系统架构 二、Flink架构 2.1 Flink的设计架构 Flink是一个分层的架构系统&#xff0c;每一层所包含的组件都提供了特定的抽象&#xff0c;用来服务于上层组件&#xff0c;Flink的分层体…

搬家货运系统软件开发功能

生活中要用到搬家的场景很多&#xff0c;租房子、买房子、换房子都要搬家&#xff0c;不管是从时间还是专业性上来说&#xff0c;很多人都更愿意找专业的搬家公司来代为处理&#xff0c;于是市面上出现了各类各样的货运搬家软件&#xff0c;让有需求的用户可以直接在线预约搬家…

Java实现网上人才招聘系统【附源码】

网上人才招聘系统 1、概述 3 2、系统分析 4 2.1、问题定义 4 2.2、可行性研究 4 2.2.1、可行性需求分析 4 2.2.2、数据流分析 5 2.2.3、数据字典 6 2.2.4、程序流程图 6 2.2.4、开发进度计划 6 2.3、需求分析 7 2.3.1、功能需求分析 7 2.3.2、数据需求分析 10 2.3.3、性能需求…

Dozer拷贝DO到VO

DO&#xff1a; data object 查出来的数据 VO&#xff1a; value object 要展示的数据&#xff0c;返回给前端的数据 DO查出来的字段比较多&#xff0c;VO过滤一下返回给前端 工具类Dozer <dependency><groupId>com.github.dozermapper</groupId><arti…

Vue3 router路由跳转传参Json数据,隐藏参数Url不显示跳转内容,使用History 来写,setup语法糖的写法

前言&#xff1a;Vue3中 Router的自2022-8-22 日后不能使用 params传参 —— 可以这么写&#xff0c;但是接收的时候会是空值 —— query可以用但不能用隐藏Url地址内的值&#xff0c;所以我们用History来写 history敲不出来的可以看最下面 这个相当于history模式父级调到子集后…

Linux文本三剑客之~~~awk 详细讲解 与date粗略讲解

目录 一. awk工作原理&#xff1a;1.1命令格式:1.2 awk常见的内建变量(可直接用)如下所示: 二 实验示例2.1 按行输出文本2.2按字段输出文本2.3 通过管道符双引号调用shell命令 date命令 一. awk工作原理&#xff1a; 逐行读取文本&#xff0c;默认以空格或tab键为分隔符进行分…

软件测试月薪2万,需要技术达到什么水平?

最近跟朋友在一起聚会的时候&#xff0c;提了一个问题&#xff0c;说一个软件测试工程师如何能月薪达到二万&#xff0c;技术水平需要达到什么程度&#xff1f;人回答说这只能是大企业或者互联网企业工程师才能拿到。也许是的&#xff0c;小公司或者非互联网企业拿二万的不太可…

网络性能监控(NPM)工具

网络是每个企业的支柱。即使在小型或企业级企业中&#xff0c;网络中断期间的生产力损失也可能导致巨大的损失。网络监控解决方案可帮助您预测潜在的中断并主动解决网络问题。这有助于维护无拥塞网络&#xff0c;使您的业务保持正常运行。这可以在网络监控工具的帮助下实现。网…

spring boot 完整后端接口案例

第一章 会员管理项目父模块搭建 1.1 创建模块mengxuegu-member mengxuegu-member 作为所有工程的父工程&#xff0c;用于管理项目的所有依赖。 1.2 添加pom依赖&#xff0c;pom.xml 文件位于&#xff1a;会员管理系统/03-配套资料/pom文件/member-pom.xml <?xml version&…

自建minio实现doris的快速备份与恢复

一.概述 doris支持通过腾讯云bos、阿里云oss、hdfs实现备份与恢复&#xff0c;但是我们公司doris部署在线下机房&#xff0c;如采用oss/bos, 大数据备份与恢复比较慢&#xff0c;会占用一定的带宽&#xff0c;如采用hdfs&#xff0c;担心小文件太多影响现有的hadoop集群。为了保…

C# Forecast 预测数据方法,MathNet.Numerics学习分享

Forecast 数据预测 /// <summary>/// 数据预测/// </summary>/// <param name"xValues">数据序列</param>/// <param name"yValues">数据值</param>/// <param name"forecastPoint">第N个预测序列<…

腾讯面试经验,岗位是C++后端

分享一篇腾讯面经&#xff0c;岗位是C后端&#xff0c;考察的内容是C、Redis、网络。 c shared_ptr的原理 答&#xff1a;内部的共享数据和引用计数实现 补充&#xff1a; shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数&#xff0c;每一个shared_ptr的拷贝都…

【瑞萨RA系列FSP库开发】RASC+Keil的环境搭建

文章目录 一、获取资源包二、安装 Keil 软件、RA 芯片包和 RASC三、RASC 集成到 Keil四、使用 RASC 生成 Keil 工程五、通过 Keil 打开 RASC 的 FSP 配置器界面六、配置和编译 Keil 工程七、使用调试器下载程序 本节将介绍如何在Keil上开发瑞萨RA MCU &#xff08;如需了解 e2 …

元宇宙虚拟展馆和VR的关系与区别

元宇宙是指一个数字化的虚拟世界&#xff0c;这个世界由虚拟现实、增强现实等多种技术构建而成。这个世界中&#xff0c;人们可以用虚拟身份在其中自由穿梭&#xff0c;享受到与现实世界不同的多样化和极致体验。虚拟现实&#xff08;VR&#xff09;则是一种技术手段&#xff0…

一文吃透3类CSS复合选择器【案例演示】

书写CSS样式表时&#xff0c;可以使用CSS基础选择器选中HTML元素。但是在实际网站开发中&#xff0c;一个网页可能包含成千上万的HTML元素&#xff0c;如果仅使用CSS基础选择器是远远不够的。为此&#xff0c;CSS提供了儿种复合选择器&#xff0c;实现了更强、更方便的选择功能…