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

QT实现曲线图缩放、拖拽以及框选放大

.h文件

protected:    void saveAxisRange();void wheelEvent(QWheelEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;private:QPoint m_lastPoint;bool m_isPress = false;  //这里我把平移的判定初始化成了false,解决鼠标一移进QchartView就跟随移动的情况bool m_ctrlPress;bool m_alreadySaveRange;double m_xMin, m_xMax, m_yMin, m_yMax;QGraphicsSimpleTextItem* m_coordItem;// 框选bool m_isSelecting = false;        // 是否正在框选QPoint m_selectionStart;           // 框选起点QGraphicsRectItem* m_selectionRect = nullptr; // 选框图形项

.cpp文件

void saveAxisRange()
{QValueAxis *axisX = dynamic_cast<QValueAxis*>(this->chart()->axisX());m_xMin = axisX->min();m_xMax = axisX->max();QValueAxis *axisY = dynamic_cast<QValueAxis*>(this->chart()->axisY());m_yMin = axisY->min();m_yMax = axisY->max();
}void wheelEvent(QWheelEvent *event)
{获取当前轴的缩放因子(0.9为缩小,1.1为放大)//const double zoomFactor = 0.9;//const double minRange = 0.01; // 防止缩放到负数或过小获取当前轴范围//QValueAxis* axisX = qobject_cast<QValueAxis*>(chart()->axes(Qt::Horizontal).first());//QValueAxis* axisY = qobject_cast<QValueAxis*>(chart()->axes(Qt::Vertical).first());//if(!axisX || !axisY)//{//    return;//}计算缩放方向(向上滚为缩小,向下滚为放大)//double delta = event->angleDelta().y() > 0 ? zoomFactor : 1.0 / zoomFactor;根据修饰键选择缩放轴//if(event->modifiers() & Qt::ControlModifier)//{//    // 缩放Y轴//    double newMinY = axisY->min() * delta;//    double newMaxY = axisY->max() * delta;//    if(newMaxY - newMinY > minRange)//    {//        axisY->setRange(newMinY, newMaxY);//    }//}//else//{//    // 缩放X轴//    double newMinX = axisX->min() * delta;//    double newMaxX = axisX->max() * delta;//    if(newMaxX - newMinX > minRange)//    {//        axisX->setRange(newMinX, newMaxX);//    }//}//event->accept();const QPoint curPos = event->pos();QPointF curVal = this->chart()->mapToValue(QPointF(curPos));if(!m_alreadySaveRange){this->saveAxisRange();m_alreadySaveRange = true;}const double factor = 1.5;//缩放比例if(event->modifiers() & Qt::ControlModifier){//Y轴QValueAxis *axisY = dynamic_cast<QValueAxis*>(this->chart()->axisY());const double yMin = axisY->min();const double yMax = axisY->max();const double yCentral = curVal.y();double bottomOffset;double topOffset;if(event->delta() > 0){//放大bottomOffset = 1.0 / factor * (yCentral - yMin);topOffset = 1.0 / factor * (yMax - yCentral);}else{//缩小bottomOffset = 1.0 * factor * (yCentral - yMin);topOffset = 1.0 * factor * (yMax - yCentral);}this->chart()->axisY()->setRange(yCentral - bottomOffset, yCentral + topOffset);}else{//X轴QValueAxis *axisX = dynamic_cast<QValueAxis*>(this->chart()->axisX());const double xMin = axisX->min();const double xMax = axisX->max();const double xCentral = curVal.x();double leftOffset;double rightOffset;if(event->delta() > 0){//放大leftOffset = 1.0 / factor * (xCentral - xMin);rightOffset = 1.0 / factor * (xMax - xCentral);}else{//缩小leftOffset = 1.0 * factor * (xCentral - xMin);rightOffset = 1.0 * factor * (xMax - xCentral);}this->chart()->axisX()->setRange(xCentral - leftOffset, xCentral + rightOffset);}
}void mousePressEvent(QMouseEvent *event)
{//if(event->button() == Qt::LeftButton)//{//    m_lastPoint = event->pos();//    m_isPress = true;//}if(event->button() == Qt::LeftButton){// 检测 Ctrl 键是否按下if(QApplication::keyboardModifiers() & Qt::ControlModifier){// 开始框选m_isSelecting = true;m_selectionStart = event->pos();// 创建选框图形项if(!m_selectionRect){m_selectionRect = new QGraphicsRectItem();m_selectionRect->setPen(QPen(Qt::blue, 1, Qt::DashLine));m_selectionRect->setBrush(QColor(100, 100, 255, 50));chart()->scene()->addItem(m_selectionRect);}}else{// 正常平移模式m_lastPoint = event->pos();m_isPress = true;}}
}void mouseMoveEvent(QMouseEvent *event)
{/*if(!m_coordItem){m_coordItem = new QGraphicsSimpleTextItem(this->chart());m_coordItem->setZValue(5);m_coordItem->setPos(100, 60);m_coordItem->show();}const QPoint curPos = event->pos();if(m_isPress){QPoint offset = curPos - m_lastPoint;m_lastPoint = curPos;if(!m_alreadySaveRange){this->saveAxisRange();m_alreadySaveRange = true;}this->chart()->scroll(-offset.x(), offset.y());}*/// 更新坐标显示(原功能保留)if(!m_coordItem){m_coordItem = new QGraphicsSimpleTextItem(chart());m_coordItem->setZValue(5);m_coordItem->setPos(100, 60);}// 处理框选逻辑if(m_isSelecting){// 更新选框图形QRectF rect(m_selectionStart, event->pos());m_selectionRect->setRect(rect.normalized());}// 处理平移逻辑else if(m_isPress){QPoint offset = event->pos() - m_lastPoint;m_lastPoint = event->pos();if(!m_alreadySaveRange){saveAxisRange();m_alreadySaveRange = true;}chart()->scroll(-offset.x(), offset.y());}
}void mouseReleaseEvent(QMouseEvent *event)
{//m_isPress = false;//if(event->button() == Qt::RightButton)//{//    if(m_alreadySaveRange)//    {//        this->chart()->axisX()->setRange(m_xMin, m_xMax);//        this->chart()->axisY()->setRange(m_yMin, m_yMax);//    }//}if(event->button() == Qt::LeftButton){if(m_isSelecting){// 应用框选缩放QRectF rect = m_selectionRect->rect();QPointF topLeft = chart()->mapToValue(rect.topLeft());QPointF bottomRight = chart()->mapToValue(rect.bottomRight());chart()->axisX()->setRange(topLeft.x(), bottomRight.x());chart()->axisY()->setRange(bottomRight.y(), topLeft.y()); // Y轴方向反转// 清理选框chart()->scene()->removeItem(m_selectionRect);delete m_selectionRect;m_selectionRect = nullptr;m_isSelecting = false;}else{m_isPress = false;}}// 原右键恢复功能保留else if(event->button() == Qt::RightButton){if(m_alreadySaveRange){chart()->axisX()->setRange(m_xMin, m_xMax);chart()->axisY()->setRange(m_yMin, m_yMax);}}
}

构造函数中添加代码:

    grabGesture(Qt::PinchGesture);                              //这里只grabGesture了PinchGesture

http://www.xdnf.cn/news/339967.html

相关文章:

  • 10.进程控制(下)
  • PyTorch 入门与核心概念详解:从基础到实战问题解决
  • 卷积神经网络基础(八)
  • (leetcode) 力扣100 7.接雨水(两种非官解,三种官解,对官解进一步解释)
  • MCP vs Function Call:AI交互的USB-C革命
  • Amazon Redshift 使用场景解析与最佳实践
  • 快速上手Pytorch Lighting框架 | 深度学习入门
  • 华为HCIP-AI认证考试版本更新通知
  • 自定义Widget开发:自定义布局实现
  • Redis 重回开源怀抱:开源精神的回归与未来展望
  • 终极终端体验:Warp 使用完全指南
  • 事务(transaction)-中
  • Opencv进阶操作:图像拼接
  • 【金仓数据库征文】金仓数据库:创新驱动,引领数据库行业新未来
  • 电容知识小结
  • LeetCode第284题 - 窥视迭代器
  • 立式筒仓式发酵槽实验台试验装置
  • Lua从字符串动态构建函数
  • LeetCode 热题 100 238. 除自身以外数组的乘积
  • IC ATE集成电路测试学习——PLL测试(一)
  • Redis-商品缓存
  • pycharm无法导入相对路径下其它文件
  • 性能远超SAM系模型,苏黎世大学等开发通用3D血管分割基础模型
  • 【造包工具】【Xcap】精讲Xcap构造分片包(IPv4、ipv6、4G\5G等pcap均可),图解超赞超详细!!!
  • 开发者如何优雅应对HTTPS抓包难题
  • 智能量化策略开发全流程:数据准备,因子计算,因子分析,模型训练,策略构建(附python代码)
  • 硬件选型:工控机的选择要素
  • 00 Ansible简介和安装
  • ubuntu 22.04 换源
  • 【Linux】FreeRTOS与Linux:实时与通用的终极对比