QCustomPlot实现曲线拖拽

本文内容目录

    • 需求场景:
    • 一、选择控件
    • 二、将QCustomPlot库整合到你的Qt项目中
        • 1、下载源代码
        • 2、创建.pri
    • 三、鼠标框选,实现坐标缩放
    • 四、曲线拖动
        • 1、定位曲线
        • 2、移动时改变曲线
    • 五、问题的产生与解决
        • 1、查看源码
        • 2、修改本项目代码

需求场景:

曲线图应该同时具有以下功能点:
1、在画布上进行鼠标框选,实现坐标缩放。
2、可以上下拖动某曲线。

在这里插入图片描述

一、选择控件

这里选择QCustomPlot,是一个C++绘图库,可以创建各种类型的绘图,包括散点图、曲线图、直方图、颜色地图、轮廓图等,可以跨平台使用。

以下是QCustomPlot的官方文档:
QCustomPlot官方网站
https://www.qcustomplot.com/

二、将QCustomPlot库整合到你的Qt项目中

1、下载源代码

在这里插入图片描述

2、创建.pri

.pri文件的内容添加如下:

HEADERS += \$$PWD/qcustomplot.hSOURCES += \$$PWD/qcustomplot.cpp

将.pri文件,.cpp文件,.h文件放到同一个文件夹下,示例项目为PlotTest。:
在这里插入图片描述
并在项目配置文件.pro文件中添加语句:

include(CustomPlot/CustomPlot.pri)

重新构建后,可以看到qcustomplot库已经整合到项目中:
在这里插入图片描述

三、鼠标框选,实现坐标缩放

实现代码:mCustomPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
mCustomPlot->setSelectionRectMode(QCP::SelectionRectMode::srmZoom);

说明:

mCustomPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);setInteractions 函数配置图表的交互方式:QCP::iRangeDrag:启用拖动操作,允许在图表上拖动以平移视图(画布的拖动而非拖动曲线)。
QCP::iRangeZoom:启用缩放操作,允许在图表上进行鼠标滚轮缩放或选择区域以进行缩放。
QCP::iSelectPlottables:启用可选择图表元素的操作。这允许你在图表上单击选择图形元素,以便进行进一步的操作或分析。前两个选项用于框选,后一个选项支持曲线拖动。
mCustomPlot->setSelectionRectMode(QCP::SelectionRectMode::srmZoom);setSelectionRectMode 函数配置选择矩形的工作模式:QCP::srmNone:禁用选择矩形,用户无法使用选择矩形进行任何操作。
QCP::srmZoom:启用选择矩形以进行缩放操作,用户可以在图表上创建选择矩形以放大或缩小选定区域。
QCP::srmSelect:启用选择矩形以选择图表中的对象,用户可以在图表上创建选择矩形以选择图表元素,例如曲线。
QCP::srmCustom:自定义选择矩形操作模式,可以根据需要自定义操作。

这里的矩形指的是框选矩形,如下所示:
在这里插入图片描述

四、曲线拖动

要实现曲线拖动的思路是,首先要定位,知道拖动的是哪条曲线,其次是当鼠标移动时,要根据鼠标坐标改变曲线。

1、定位曲线

通过信号selectionChangedByUser获得曲线index。

connect(mCustomPlot, &QCustomPlot::selectionChangedByUser, this, &ResultCurves::getSelection);在getSelection槽函数中,可以进行处理,可以用成员变量存储当前用户选中的曲线index
2、移动时改变曲线

重写鼠标移动事件mouseMoveEvent。

void ResultCurves::mouseMoveEvent(QMouseEvent *event)
{//获取鼠标的本地窗口坐标double x = event->pos().x();double y = event->pos().y();//将鼠标指针的像素坐标转换为图表上的实际坐标double xCurve = mCustomPlot->xAxis->pixelToCoord(x);double yCurve = mCustomPlot->yAxis->pixelToCoord(y);//获取当前图表显示的y轴最大坐标,这里用于限制曲线的移动坐标范围double yMax = mCustomPlot->yAxis->range().upper;double yMin = mCustomPlot->yAxis->range().lower;mPosX = xCurve;mPosY = yCurve;if(mPosY > yMax){mPosY = yMax;}if(mPosY < yMin){mPosY = yMin;}//当目标曲线被选中时,在drawThresholdLine中进行曲线的重新绘制if(mIsThresholdSelected){drawThresholdLine(mPosY);}
}void ResultCurves::drawThresholdLine(double yValue)
{//在QCustomPlot对象和mGraphList曲线列表中删除目标曲线mCustomPlot->removeGraph(mGraphList.size() - 1);mGraphList.removeLast();//新增更新曲线QVector<double> temp;for(int i=0; i<mCurveList.begin().value().size(); i++){temp.append(yValue);}addCurve(mGraphList.size(),mXValues,temp);mCustomPlot->replot();
}

五、问题的产生与解决

可以发现,以上两个功能的触发方式都是鼠标左键单击,经过实践,qcustomplot不能区分鼠标左键单击后是执行框选还是拖动,即使是在mousepressevent中判断是否选中目标曲线,若选中则mCustomPlot->setSelectionRectMode(QCP::SelectionRectMode::srmNone);(禁用矩形),也不能使两个功能共存。

1、查看源码

发现在QCustomPlot::mouseMoveEvent中,调用到一个函数processPointSelection:
在这里插入图片描述
该函数处理鼠标事件,特别是点选操作,也仅在QCustomPlot::mouseMoveEvent中调用。如果发生了选择状态的更改(selectionStateChanged 为 true),则发出 selectionChangedByUser 信号。
所以一个简单直接的思路是,当我想框选时,不调用该函数,不进行点选操作;当我想拖动时,调用该函数,发出 selectionChangedByUser 信号。
因此增加一个bool变量和接口:在这里插入图片描述
在这里插入图片描述

2、修改本项目代码

在以上更改后,在我们自定义类的mousePressEvent中,当选中曲线index为目标曲线index时:

mCustomPlot->setSelectionRectMode(QCP::SelectionRectMode::srmNone);
mCustomPlot->setHoverPicked(false);

而在mouseReleaseEvent中:

mCustomPlot->setSelectionRectMode(QCP::SelectionRectMode::srmZoom);

从而最终可以满足文章开头的需求任务。

欢迎一起讨论!

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

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

相关文章

excel 日期与时间戳的相互转换

1、日期转时间戳&#xff1a;B1INT((A1-70*365-19)*86400-8*3600)*1000 2、时间戳转日期&#xff1a;A1TEXT((B1/10008*3600)/8640070*36519,"yyyy-mm-dd hh:mm:ss") 以上为精确到毫秒&#xff0c;只精确到秒不需要乘或除1000。 使用以上方法可以进行excel中日期…

行业追踪,2023-10-18

自动复盘 2023-10-18 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

Redis LFU缓存淘汰算法

前言 Redis 在 4.0 版本之前的缓存淘汰算法&#xff0c;只支持 random 和 lru。random 太简单粗暴了&#xff0c;可能把热点数据给淘汰掉&#xff0c;一般不会使用。lru 比 random 好一点&#xff0c;会优先淘汰最久没被访问的数据&#xff0c;但是它也有一个缺点&#xff0c;…

英语——分享篇——每日200词——1001-1200

1001——responsibility——[rɪˌspɒnsəbɪlətɪ]——n.责任——responsibility——res热死(拼音)ponsi胖子(谐音)bili比利(拼音)ty题(谐音)——热死的胖子比利做题时很有责任心——The responsibility for her family bears down on a young woman.——家庭的责任沉重地落…

攻防世界web篇-PHP2

直接点击进入到http网页中&#xff0c;会得到这样一个界面 这里&#xff0c;我最开始使用了burp什么包也没有抓到&#xff0c;然后接着又用nikto进行探测&#xff0c;得到的只有两个目录&#xff0c;当时两个目录打开后&#xff0c;一个是fond界面&#xff0c;一个是这个网页的…

【QT】常用控件——按钮组

继承Widget PushButton 设置图片&#xff0c;先导入图片资源&#xff0c;见&#xff1a;【QT】资源文件导入_复制其他项目中的文件到qt项目中_StudyWinter的博客-CSDN博客 在布局中添加图片 调整尺寸 toolButton 显示图片、文本 显示图片&#xff08;图片和文字都有时&#…

使用Python+selenium实现第一个自动化测试脚本

这篇文章主要介绍了使用Pythonselenium实现第一个自动化测试脚本&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值&#xff0c;需要的朋友们下面随着小编来一起学习学习吧 最近在学web自动化&#xff0c;记录一下学习过程。…

快速解决 Resource not accessible by integration

简介 最近好久没有写博客了&#xff0c;今天在写开源项目 python-package-template 的时候&#xff0c;正好遇到一个问题&#xff0c;记录一下吧。本文将介绍 Resource not accessible by integration 的几种解决方案。 也欢迎大家体验一下 python-package-template 这个项目&…

黑白棋(Othello, ACM/ICPC World Finals 1992, UVa220)rust解法

你的任务是模拟黑白棋游戏的进程。黑白棋的规则为&#xff1a;黑白双方轮流放棋子&#xff0c;每次必须让新放的棋子“夹住”至少一枚对方棋子&#xff0c;然后把所有被新放棋子“夹住”的对方棋子替换成己方棋子。一段连续&#xff08;横、竖或者斜向&#xff09;的同色棋子被…

SpringCloud: sentinel热点参数限制

一、定义controller package cn.edu.tju.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import org.springframework.web.bind.annotation.PathVariable; import org.springframewo…

Unity笔记--渲染顺序

目录 Unity中的渲染顺序一、Camera层二、透明类型&#xff08;先渲染不透明&#xff09;三、物体的SortingLayer&#xff08;越小越先渲染&#xff09;四、sorting order&#xff08;越小越先渲染&#xff09;五、RenderQueue &#xff08;越小越优先&#xff09;六、距离相机z…

【算法设计zxd】第6章 回溯法

目录 6.1 回溯法的设计技术 &#xff1a; 四皇后问题 回溯法&#xff1a; 算法框架&#xff1a; 思考题&#xff1a; 回溯算法的适用条件 【例6-1】求满足下列不等式的所有整数解&#xff1a; 6.2回溯算法的经典例题 【例6-2】装载问题  问题分析 计算模型  算法设计与描…

BookStack 详解及 Docker-Compose 部署

BookStack 是一款用于创建文档和文档管理的开源平台。它提供了一个直观且功能丰富的界面&#xff0c;可用于组织和管理各种文档&#xff0c;包括文档编写、编辑和共享。本文将介绍 BookStack 的核心功能&#xff0c;并展示如何使用 Docker-Compose 快速部署 BookStack。 BookS…

Pika v3.5.1发布!

Pika 社区很高兴宣布&#xff0c;我们今天发布已经过我们生产环境验证 v3.5.1 版本&#xff0c;https://github.com/OpenAtomFoundation/pika/releases/tag/v3.5.1 。 该版本不仅做了很多优化工作&#xff0c;还引入了多项新功能。这些新功能包括 动态关闭 WAL、ReplicationID…

BI零售数据分析,当代零售企业的核心竞争力

在数字化转型中&#xff0c;BI智能零售数据分析成为了极其重要的核心竞争力之一。通过对大数据的采集和分析&#xff0c;零售企业可以更好地了解消费者的需求和行为模式&#xff0c;从而做出更准确的决策。例如&#xff0c;通过分析消费者的购物历史、浏览记录等数据&#xff0…

CLIP模型原理

CLIP模型 CLIP(Contrastive Language-Image Pre-Training) 模型是 OpenAI 在 2021 年初发布的用于匹配图像和文本的预训练神经网络模型&#xff0c;是近年来在多模态研究领域的经典之作。OpenAI 收集了 4 亿对图像文本对&#xff08;一张图像和它对应的文本描述&#xff09;&a…

Messari发布Moonbeam简报,每日交易量稳步增长,首次公布利润数据

区块链数据公司Messari首次发布Moonbeam项目分析简报&#xff0c;从项目市值、链上数据表现、质押以及Moonbeam的技术优势XCM使用量等角度全面分析。这个再熊市初期上线的项目一直在默默开发&#xff0c;并在跨链互操作领域拥有了相当的实操成绩。我们翻译了Messari简报中的部分…

【Vue项目】通过设置全局的异常处理来统一处理后端返回的异常

文章目录 简介方法一创建统一异常处理模块使用axios拦截器处理异常在页面中使用异常处理 方法二创建全局异常处理函数在main.js中配置全局异常处理在网络请求中捕获异常 方法三创建全局异常处理插件在main.js中注册全局异常处理插件在网络请求中捕获异常 总结 简介 在Vue项目中…

aps.net core 6.0 web API SwaggerUI IIS部署【23.10.15】亲测,通过

目录 一、aps.net core 6.0 web API 项目配置 创建项目设置 Swagger UI 为起始页发布项目二、在 IIS 部署 安装IIS安装 Hosting Bundle三、内网穿透 使用的是 VS2022社区版&#xff0c;WebAPI的版本是 .netcore6.0 一、aps.net core 6.0 web API 项目配置 1.创建项目 运行项目…

计算机毕业设计 基于Spring Boot智能停车计费系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…