当前位置: 首页 > news >正文

Qt篇——QChartView实现鼠标滚轮缩放、鼠标拖拽平移、鼠标双击重置缩放平移、曲线点击显示坐标

话不多说。

第一步:自定义QChartView,直接搬

FirtCurveChartView.h

#ifndef FITCURVECHARTVIEW_H
#define FITCURVECHARTVIEW_H
#include <QtCharts>class FitCurveChartView : public QChartView {Q_OBJECTpublic:FitCurveChartView(QWidget *parent = Q_NULLPTR);~FitCurveChartView();protected:void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);void mouseDoubleClickEvent(QMouseEvent *event);void wheelEvent(QWheelEvent *event);signals:void signalMouseEvent(int eventId, QMouseEvent *event);void signalWheelEvent(QWheelEvent *event);};#endif // FITCURVECHARTVIEW_H

FirtCurveChartView.cpp

#include "FitCurveChartView.h"FitCurveChartView::FitCurveChartView(QWidget *parent) {}FitCurveChartView::~FitCurveChartView() {}void FitCurveChartView::mousePressEvent(QMouseEvent *event) {emit signalMouseEvent(0, event);QChartView::mousePressEvent(event);
}void FitCurveChartView::mouseMoveEvent(QMouseEvent *event) {emit signalMouseEvent(1, event);QChartView::mouseMoveEvent(event);
}void FitCurveChartView::mouseReleaseEvent(QMouseEvent *event) {emit signalMouseEvent(2, event);QChartView::mouseReleaseEvent(event);
}void FitCurveChartView::mouseDoubleClickEvent(QMouseEvent *event) {emit signalMouseEvent(3, event);QChartView::mouseDoubleClickEvent(event);
}void FitCurveChartView::wheelEvent(QWheelEvent *event) {emit signalWheelEvent(event);QChartView::wheelEvent(event);
}

第二步:在主界面代码中使用,我的是在自定义对话框里面,你们可以直接在窗口中使用

举例:fitcurvedialog.h

#ifndef FITCURVEDIALOG_H
#define FITCURVEDIALOG_H#include <QDialog>
#include "FitCurveChartView.h"namespace Ui {
class FitCurveDialog;
}class FitCurveDialog : public QDialog
{Q_OBJECTpublic:explicit FitCurveDialog(QWidget *parent = nullptr);~FitCurveDialog();void initQChartView();void updateXYGuideLine();void resetZoomAndScroll();QVector<int> getAxisRanges();public slots:void theSlotMouseEvent(int eventId, QMouseEvent *event);void theSlotWheelEvent(QWheelEvent *event);private:Ui::FitCurveDialog *ui;FitCurveChartView *curveChartView;QChart *curveChart;QSplineSeries* fitPointsSeriesS;    //要显示的曲线原始数据QScatterSeries* tipSeries;QSplineSeries* xGuideSeries;    //鼠标悬浮位置点的x轴辅助线QSplineSeries* yGuideSeries;    //鼠标悬浮位置点的y轴辅助线bool isPressed = false;         //图标是否在拖拽中QPoint pressedPoint;            //鼠标拖拽起点};#endif // FITCURVEDIALOG_H

fitcurvedialog.cpp    (UI文件里面就放了一个水平布局chartLayout)

#include "fitcurvedialog.h"
#include "ui_fitcurvedialog.h"FitCurveDialog::FitCurveDialog(QWidget *parent) :QDialog(parent),ui(new Ui::FitCurveDialog)
{ui->setupUi(this);qApp->setOverrideCursor(Qt::ArrowCursor);       //允许系统弹窗、提示initQChartView();
}void FitCurveDialog::initQChartView() {//创建图表框架curveChartView = new FitCurveChartView(this);curveChartView->setMaximumWidth(1730);curveChartView->setMinimumHeight(480);curveChart = new QChart();curveChart->setTheme(QChart::ChartThemeBlueIcy);curveChart->setContentsMargins(0, 0, 0, 0);             //设置外边界全部为0, 根据自己实际情况设置curveChart->setMargins(QMargins(5, -30, 5, 10));        //设置内边界, 根据自己实际情况设置curveChart->setBackgroundRoundness(0);                  //设置表格边框圆角半径curveChartView->setChart(curveChart);//创建折线序列fitPointsSeriesS = new QSplineSeries(this);               //原始数据曲线fitPointsSeriesS->setUseOpenGL(true);xGuideSeries = new QSplineSeries(this);yGuideSeries = new QSplineSeries(this);tipSeries =  new QScatterSeries();                      // 创建一个散点数据集对象,用于显示tipSeries->setMarkerShape(QScatterSeries::MarkerShapeCircle);  // 设置绘制的散点的样式为圆tipSeries->setMarkerSize(10);QObject::connect(fitPointsSeriesS, &QSplineSeries::clicked, [=](const QPointF &point)mutable{QPointF tempPoint;QVector<QPointF> tempList(fitPointsSeriesS->pointsVector());  //复制曲线中的数据进行计算, 因为直接使用会导致卡顿int tempX = qRound(point.x());int tempY = -999;for (int i = 0; i < tempList.size(); i++) {if (tempList[i].x() == tempX) {tempY = tempList[i].y();tempPoint.setX(tempX);tempPoint.setY(tempY);break;}}if (tempY != -999) {QToolTip::showText(QCursor::pos(), QString("(%1,%2)").arg(tempX).arg(tempY));QVector<QPointF> tipList;tipList.append(tempPoint);tipSeries->replace(tipList);updateXYGuideLine();}});curveChart->addSeries(xGuideSeries);curveChart->addSeries(yGuideSeries);curveChart->addSeries(fitPointsSeriesS);curveChart->addSeries(tipSeries);//添加数据绘制size_t count = 20000;QVector<QPointF> list;for (size_t i = 0; i < count; i++) {list.append(QPoint(i, int(i / 40)));}fitPointsSeriesS->replace(list);//创建坐标轴QValueAxis* axisX = new QValueAxis;axisX->setRange(0, 20000);axisX->setTickCount(21);axisX->setLabelFormat("%d");axisX->setLabelsAngle(-90);      //坐标刻度文字显示角度curveChart->addAxis(axisX,Qt::AlignBottom);xGuideSeries->attachAxis(axisX);yGuideSeries->attachAxis(axisX);fitPointsSeriesS->attachAxis(axisX);tipSeries->attachAxis(axisX);QValueAxis* axisY = new QValueAxis;axisY->setRange(0, 500);axisY->setTickCount(11);axisY->setLabelFormat("%d");curveChart->addAxis(axisY,Qt::AlignLeft);xGuideSeries->attachAxis(axisY);yGuideSeries->attachAxis(axisY);fitPointsSeriesS->attachAxis(axisY);tipSeries->attachAxis(axisY);//    axisX->setGridLineVisible(false);   //隐藏背景网格X轴框线
//    axisY->setGridLineVisible(false);   //隐藏背景网格Y轴框线curveChart->legend()->markers()[0]->setVisible(false);curveChart->legend()->markers()[1]->setVisible(false);curveChart->legend()->markers()[2]->setVisible(false);curveChart->legend()->markers()[3]->setVisible(false);curveChartView->setRenderHint(QPainter::Antialiasing);  //除锯齿connect(curveChartView, &FitCurveChartView::signalMouseEvent, this, &FitCurveDialog::theSlotMouseEvent);connect(curveChartView, &FitCurveChartView::signalWheelEvent, this, &FitCurveDialog::theSlotWheelEvent);ui->chartLayout->addWidget(curveChartView);
}void FitCurveDialog::theSlotMouseEvent(int eventId, QMouseEvent *event) {if (eventId == 0){  //单击按下isPressed = true;QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);pressedPoint = mouseEvent->pos();} else if (eventId == 1) {  //鼠标移动if (isPressed) {QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);curveChart->scroll(-(mouseEvent->pos().x() - pressedPoint.x()) / 10,(mouseEvent->pos().y() - pressedPoint.y()) / 10);updateXYGuideLine();}} else if (eventId == 2) {  //单击抬起isPressed = false;} else if (eventId == 3) {  //双击resetZoomAndScroll();updateXYGuideLine();}
}void FitCurveDialog::theSlotWheelEvent(QWheelEvent *event) {int delta = event->angleDelta().y();if (delta > 0) {curveChart->zoom(0.95);} else {curveChart->zoom(1.05);}updateXYGuideLine();
}void FitCurveDialog::updateXYGuideLine() {if (tipSeries->points().size() > 0) {QVector<int> axisRanges = getAxisRanges();QVector<QPointF> xGuideList, yGuideList;int tempX = tipSeries->points()[0].x();int tempY = tipSeries->points()[0].y();xGuideList.append(QPointF(tempX, axisRanges[2]));xGuideList.append(QPointF(tempX, tempY));yGuideList.append(QPointF(axisRanges[0], tempY));yGuideList.append(QPointF(tempX, tempY));xGuideSeries->replace(xGuideList);yGuideSeries->replace(yGuideList);}
}void FitCurveDialog::resetZoomAndScroll() {curveChart->zoomReset();QList<QAbstractAxis*> axesX, axesY;axesX = curveChart->axes(Qt::Horizontal);axesY = curveChart->axes(Qt::Vertical);QValueAxis *curAxisX = (QValueAxis*)axesX[0];QValueAxis *curAxisY = (QValueAxis*)axesY[0];curAxisX->setRange(0, 20000);curAxisY->setRange(0, 500);
}QVector<int> FitCurveDialog::getAxisRanges() {QList<QAbstractAxis*> axesX, axesY;axesX = curveChart->axes(Qt::Horizontal);axesY = curveChart->axes(Qt::Vertical);QValueAxis *curAxisX = (QValueAxis*)axesX[0];QValueAxis *curAxisY = (QValueAxis*)axesY[0];QVector<int> ranges = {int(curAxisX->min()), int(curAxisX->max()), int(curAxisY->min()), int(curAxisY->max())};return ranges;
}FitCurveDialog::~FitCurveDialog()
{delete ui;
}

效果:(动图依次展示:①点击曲线显示坐标->②平移->③缩放->④双击还原)

相关文章:

Qt篇——QChartView实现鼠标滚轮缩放、鼠标拖拽平移、鼠标双击重置缩放平移、曲线点击显示坐标

话不多说。 第一步&#xff1a;自定义QChartView&#xff0c;直接搬 FirtCurveChartView.h #ifndef FITCURVECHARTVIEW_H #define FITCURVECHARTVIEW_H #include <QtCharts>class FitCurveChartView : public QChartView {Q_OBJECTpublic:FitCurveChartView(QWidget *…...

掌握VUE中localStorage的使用

文章目录 &#x1f341;localStorage的使用&#x1f33f;设置数据&#x1f33f;获取数据&#x1f33f;更新数据&#x1f33f;删除数据 &#x1f341;代码示例&#x1f341;使用场景&#x1f341;总结 localStorage是一种Web浏览器提供的本地存储机制&#xff0c;允许开发者在用…...

所有行业的最终归宿-我有才打造知识付费平台

随着科技的不断进步和全球化的加速发展&#xff0c;我们生活在一个信息爆炸的时代。各行各业都在努力适应这一变化&#xff0c;寻找新的商业模式和增长机会。在这个过程中&#xff0c;一个趋势逐渐凸显出来&#xff0c;那就是知识付费。可以说&#xff0c;知识付费正在成为所有…...

图的深度和广度优先遍历

题目描述 以邻接矩阵给出一张以整数编号为顶点的图&#xff0c;其中0表示不相连&#xff0c;1表示相连。按深度和广度优先进行遍历&#xff0c;输出全部结果。要求&#xff0c;遍历时优先较小的顶点。如&#xff0c;若顶点0与顶点2&#xff0c;顶点3&#xff0c;顶点4相连&…...

计算机毕业设计JAVA+SSM+springboot养老院管理系统

设计了养老院管理系统&#xff0c;该系统包括管理员&#xff0c;医护人员和老人三部分。同时还能为用户提供一个方便实用的养老院管理系统&#xff0c;管理员在使用本系统时&#xff0c;可以通过系统管理员界面管理用户的信息&#xff0c;也可以进行个人中心&#xff0c;医护等…...

Flutter路由的几种用法

Flutter路由跳转 基本路由跳转 ElevatedButton(onPressed: () {//基本路由跳转Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {return const SearchPage();}),);},child: const Text("基本路由跳转"), ), search.dart页面 impo…...

力扣119双周赛

第 119 场双周赛 文章目录 第 119 场双周赛找到两个数组中的公共元素消除相邻近似相等字符最多 K 个重复元素的最长子数组找到最大非递减数组的长度 找到两个数组中的公共元素 模拟 class Solution { public:vector<int> findIntersectionValues(vector<int>&…...

Redux,react-redux,dva,RTK

1.redux的介绍 Redux – 李立超 | lilichao.com 2.react-redux 1&#xff09;react-Redux将所有组件分成两大类 UI组件 只负责 UI 的呈现&#xff0c;不带有任何业务逻辑通过props接收数据(一般数据和函数)不使用任何 Redux 的 API一般保存在components文件夹下容器组件 …...

基于Java SSM框架实现高校信息资源共享平台系统【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现高校信息资源共享平台系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们…...

SpringMvc入坑系列(一)----maven插件启动tomcat

springboot傻瓜式教程用久了&#xff0c;回过来研究下SSM的工作流程&#xff0c;当然从Spring MVC开始&#xff0c;从傻瓜式入门处理请求和页面交互&#xff0c;再到后面深入源码分析。 本人写了一年多的后端和半年多的前端了。用的都是springbioot和vue&#xff0c;源码一直来…...

Leetcode—337.打家劫舍III【中等】

2023每日刷题&#xff08;五十二&#xff09; Leetcode—337.打家劫舍III 算法思想 实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(null…...

列表标签的介绍与使用

列表的作用&#xff1a; 整齐、整洁、有序&#xff0c;它作为布局会更加自由和方便。 根据使用情景不同&#xff0c;列表可以分为三大类&#xff1a;无序列表、有序列表和自定义列表 无序列表 <ul> 标签表示 HTML 页面中项目的无序列表&#xff0c;一般会以项目符号呈…...

浅谈什么是语音芯片的白噪音支持功能:打造舒适家居与优质音频体验

随着科技的不断进步和人们对生活质量要求的提升&#xff0c;语音芯片已经成为了现代电子产品中不可或缺的一部分。而在这些语音芯片中&#xff0c;支持白噪音的功能逐渐受到人们的关注。本文将围绕语音芯片中的白噪音支持功能展开讨论&#xff0c;带您领略其带来的舒适家居与优…...

【QED】高昂的猫 Ⅰ

目录 题目背景题目描述输入格式输出格式 测试样例样例说明数据范围 思路核心代码 题目背景 这是小橘。因为它总是看起来很高傲&#xff0c;所以人送外号“高昂的猫”。 题目描述 "锕狗"的房间里放着 n n n ( 1 ≤ n ≤ 1 0 9 ) (1 \leq n \leq 10^9) (1≤n≤109)个…...

Redis如何做内存优化?

Redis如何做内存优化&#xff1f; 1、缩短键值的长度 缩短值的长度才是关键&#xff0c;如果值是一个大的业务对象&#xff0c;可以将对象序列化成二进制数组&#xff1b; 首先应该在业务上进行精简&#xff0c;去掉不必要的属性&#xff0c;避免存储一些没用的数据&#xff1…...

倪海厦:教你正确煮中药,发挥最大药效

同样的一个汤剂&#xff0c;我开给你&#xff0c;你如果煮的方法不对&#xff0c;吃下去效果就没那么好。 所以&#xff0c;汤&#xff0c;取它的迅捷&#xff0c;速度很快&#xff0c;煮汤的时候还有技巧&#xff0c;你喝汤料的时候&#xff0c;你到底是喝它的气&#xff0c;…...

C++学习笔记:继承

继承 什么是继承?继承的写法基类和派生类的赋值转换继承中的作用域派生类的默认成员函数单继承,多继承,虚拟继承is-a 和 has-a 什么是继承? 继承是C语言面向对象的三大特性之一&#xff0c;是面向对象程序设计使代码可以复用的最重要的手段,基本都是在一个类的基础上为了增加…...

音频/视频、信息和通信技术设备安全标准UL62368-1

UL 62368-1&#xff0c;第 3 版&#xff0c;2019 年 12 月 13 日- UL 音频/视频、信息和通信技术设备安全标准 - 第 1 部分&#xff1a;安全要求 IEC 62368 的这一部分适用于该领域内电气和电子设备的安全音频、视频、信息和通信技术&#xff0c;以及额定电压不超过 600 V 的商…...

macos下安装科研绘图软件Origin

科研人必备软件Origin&#xff0c;主要是考虑到很多期刊都要求绘制origin可编辑的图&#xff0c;所以有些时候必须用这个软件&#xff0c;但是这个软件macos并不支持&#xff0c;所以必须考虑其他的方案&#xff0c;我没有安装虚拟机&#xff0c;而是使用crossover 安装crosso…...

安全快速地删除 MySQL 大表数据并释放空间

一、需求 按业务逻辑删除大量表数据操作不卡库&#xff0c;不能影响正常业务操作操作不能造成 60 秒以上的复制延迟满足以上条件的前提下&#xff0c;尽快删除数据并释放所占空间 表结构如下&#xff1a; create table space_visit_av (userid bigint(20) not null comment 用…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

学习一下用鸿蒙​​DevEco Studio HarmonyOS5实现百度地图

在鸿蒙&#xff08;HarmonyOS5&#xff09;中集成百度地图&#xff0c;可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API&#xff0c;可以构建跨设备的定位、导航和地图展示功能。 ​​1. 鸿蒙环境准备​​ ​​开发工具​​&#xff1a;下载安装 ​​De…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...