当前位置: 首页 > 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

相关文章:

  • 【特别版】Kubernetes集群安装(1master,2node)
  • docker 安装 sqlserver2022 和注意点
  • 长事务:数据库中的“隐形炸弹“——金仓数据库运维避坑指南
  • P2415 集合求和 详解
  • 需求分析阶段测试工程师主要做哪些事情
  • Kubernetes探针生产环境实战指南
  • Linux下部署Keepalived
  • 代理服务器
  • DBeaver查询PostgreSQL的只读模式
  • vue实现半圆转盘旋转(门户网页上)
  • 基于Stable Diffusion XL模型进行文本生成图像的训练
  • 旧版 Flutter 写的项目, 想要在新的环境上运行?
  • ARM 芯片上移植 Ubuntu 操作系统详细步骤
  • 【HarmonyOS 5】鸿蒙中进度条的使用详解
  • HarmonyOS-hdc远程网络方式连接设备
  • 奥威BI:AI+BI深度融合,重塑智能AI数据分析新标杆
  • SpringBoot使用定时线程池ScheduledThreadPoolExecutor
  • Android MVC架构的现代化改造:构建清晰单向数据流
  • Rspack:字节跳动自研 Web 构建工具-基于 Rust打造高性能前端工具链
  • python编译exe执行时报错:OSError:[WinError6]句柄无效
  • 巴基斯坦信德省首府卡拉奇发生爆炸
  • 云南临沧一行贿案金额认定比受贿案多41万,重审时检方变更金额起诉
  • 央行:全力推进一揽子金融政策加快落地
  • 明天起,沪苏湖高铁、杭温高铁推出13款新型票制产品
  • 金融政策支持稳市场稳预期发布会即将召开,潘功胜、李云泽、吴清将出席
  • 退休11年后,71岁四川厅官杨家卷被查