《QT实用小工具·五十》动态增删数据与平滑缩放移动的折线图

本文主要是介绍《QT实用小工具·五十》动态增删数据与平滑缩放移动的折线图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、概述
源码放在文章末尾

该项目实现了带动画、带交互的折线图,包含如下特点:
动态增删数值
自适应显示坐标轴数值
鼠标悬浮显示十字对准线
鼠标靠近点自动贴附
支持直线与平滑曲线效果
自定义点的显示类型与大小
自适应点的数值显示位置
根据指定锚点缩放
平滑的横向移动
选中的纵向渐变效果

项目demo演示如下所示:
在这里插入图片描述

项目部分代码如下所示:

#ifndef LINECHART_H
#define LINECHART_H#include <QObject>
#include <QWidget>
#include <QList>
#include <QPainter>
#include <QPainterPath>
#include <QPropertyAnimation>
#include <QtMath>struct ChartData
{QString title;QColor color = Qt::black;int xMin = 0;int xMax = 0;int yMin = 0;int yMax = 0;QList<QPoint> points;QList<QString> xLabels; // X显示的名字,可空,比如日期
};struct Vector2D : public QPointF
{Vector2D(double x, double y) : QPointF(x, y){}Vector2D(QPointF p) : QPointF(p){}/// 向量长度double length(){return sqrt(x() * x() + y() * y());}/// 转单位向量Vector2D normalize(){double len = length();double inv;if (len < 1e-4)inv = 0;elseinv = 1 / length();return Vector2D(x() * inv, y() * inv);}/// 向量相加Vector2D operator+ (Vector2D v){return Vector2D(x() + v.x(), y() + v.y());}/// 向量翻倍Vector2D operator* (double f){return Vector2D(x() * f, y() * f);}/// 内积double dot(Vector2D v){return x() * v.x() + y() * v.y();}/// 两个向量夹角double angle(Vector2D v){return acos(dot(v) / (length() * v.length())) * 180 / M_PI;}
};class LineChart : public QWidget
{Q_OBJECTQ_PROPERTY(int display_x_min READ getDisplayXMin WRITE setDisplayXMin)Q_PROPERTY(int display_x_max READ getDisplayXMax WRITE setDisplayXMax)Q_PROPERTY(int display_y_min READ getDisplayYMin WRITE setDisplayYMin)Q_PROPERTY(int display_y_max READ getDisplayYMax WRITE setDisplayYMax)public:LineChart(QWidget *parent = nullptr);int lineCount() const;void setPointLineType(int t);void setPointValueType(int t);void setPointDotType(int t);void setPointDotRadius(int r);void setLabelSpacing(int s);void addLine(ChartData data);void removeLine(int index);void addPoint(int index, int x, int y);void addPoint(int index, int x, int y, const QString& label);void removeFirst(int index);void updateAnchors();void zoom(double prop);void moveHorizontal(int x);signals:void signalSelectRangeChanged(int start, int end);public slots:void zoomIn();void zoomOut();protected:void paintEvent(QPaintEvent *event) override;void enterEvent(QEvent *event) override;void leaveEvent(QEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;void wheelEvent(QWheelEvent *event) override;private:void setDisplayXMin(int v);int getDisplayXMin() const;void setDisplayXMax(int v);int getDisplayXMax() const;void setDisplayYMin(int v);int getDisplayYMin() const;void setDisplayYMax(int v);int getDisplayYMax() const;void saveRange();void startRangeAnimation();QPropertyAnimation* startAnimation(const QByteArray &property, int start, int end, bool* flag, int duration = 300, QEasingCurve curve = QEasingCurve::OutQuad);int getValueByCursorPos(QPoint pos);private:// 数据QList<ChartData> datas;                 // 所有折线的数据// 界面QRect contentRect;                      // 显示的范围,实时刷新QRect paddings = QRect(32, 32, 32, 32); // 四周留白(width=right,height=bottom)QColor borderColor = Qt::gray;          // 边界线颜色int labelSpacing = 2;                   // 标签间距// 信息显示bool autoResize = true;                 // 自动调整大小int displayXMin = 0, displayXMax = 0;   // 显示的X轴范围int displayYMin = 0, displayYMax = 0;   // 显示的Y轴范围bool usePointXLabels = true;            // 优先使用点对应的label,还是相同间距的数值QList<QString> xLabels;                 // 显示的文字(可能少于值数量)QList<int> xLabelPoss;int pointLineType = 3;                  // 连线类型:1直线,2二次贝塞尔曲线,3三次贝塞尔曲线(更精确但吃性能)int pointValueType = 2;                 // 数值显示位置:0无,1强制上方,2自动附近int pointDotType = 1;                   // 圆点类型:0无,1空心圆,2实心圆,3小方块int pointDotRadius = 2;                 // 圆点半径// 动画效果bool enableAnimation = true;int _savedXMin, _savedXMax;             // 修改前的数值int _savedYMin, _savedYMax;bool animatingXMin = false, animatingXMax = false; // 是否正在动画中bool animatingYMin = false, animatingYMax = false;int _animatedXMin, _animatedXMax;       // 动画中的数值(仅影响显示)int _animatedYMin, _animatedYMax;// 交互数据bool pressing = false;QPoint pressPos, releasePos;bool hovering = false;QPoint hoverPos;int nearDis = 8;                        // 四周这些距离内算是“附近”// 悬浮提示bool showCrossOnPressing = true;        // 按下显示十字对准线QColor hightlightColor = QColor("#FF7300");       // 高亮颜色// 鼠标选择bool enableSelect = true;bool selecting = false;int selectPos = 0;                      // 最后一次鼠标点击的X像素(相对显示矩形)int selectXStart = 0, selectXEnd = 0;   // 鼠标按下/松开的对应X值位置QColor selectColor = QColor("#F08080"); // 选择区域颜色// 缩放(仅针对X轴)bool enableScale = true;int displayXStart = 0, displayXEnd = 0;
};#endif // LINECHART_H

源码下载

这篇关于《QT实用小工具·五十》动态增删数据与平滑缩放移动的折线图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/954099

相关文章

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

macOS无效Launchpad图标轻松删除的4 种实用方法

《macOS无效Launchpad图标轻松删除的4种实用方法》mac中不在appstore上下载的应用经常在删除后它的图标还残留在launchpad中,并且长按图标也不会出现删除符号,下面解决这个问... 在 MACOS 上,Launchpad(也就是「启动台」)是一个便捷的 App 启动工具。但有时候,应

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1