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,一经查实,立即删除!

相关文章

【算法题】2906. 构造乘积矩阵

题目&#xff1a; 给你一个下标从 0 开始、大小为 n * m 的二维整数矩阵 grid &#xff0c;定义一个下标从 0 开始、大小为 n * m 的的二维矩阵 p。如果满足以下条件&#xff0c;则称 p 为 grid 的 乘积矩阵 &#xff1a; 对于每个元素 p[i][j] &#xff0c;它的值等于除了 g…

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;图片和文字都有时&#…

容器安全 - 利用容器的特权配置实现对Kubernetes容器的攻击

《OpenShift / RHEL / DevSecOps 汇总目录》 文章目录 准备环境利用特权配置对Kubernetes容器攻击privileged hostpathprivileged hostpidprivilegedhostpathhostpidhostipchostnetwork 参考 通过将运行 Pod 的 privileged 设为 true&#xff0c;容器就以特权模式运行在宿主…

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

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

leeetcode_2530 执行k次操作后的最大分数

1. 题意 给定一个整数数组&#xff0c;每次可以取出一个数累加并丢弃&#xff0c;并将该数的1/3 向上取整放回。 执行k次操作后的最大分数 2. 题解 每次取插入后的最大值&#xff0c;所以需要大根堆。 STL里面用priority_queue<int> pq默认大根堆。 小根堆priority_…

快速解决 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…

小程序无感刷新

下载wechat-http依赖 npm install wechat-http封装请求拦截器和相应拦截器&#xff0c;借助refreshToken实现无感刷新 // 导入 http 模块 import http from wechat-http // 基础路径&#xff0c;同时需添加合法请求域名 http.baseURL https://live-api.itheima.net // 配置请…

CLIP模型原理

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