#include "panels/chart/LivePanner.hpp" #include #include #include #include #include namespace geopro::app { LivePanner::LivePanner(QwtPlot* plot, int xAxis, int yAxis, QObject* parent) : QObject(parent), plot_(plot), xAxis_(xAxis), yAxis_(yAxis) { if (plot_ && plot_->canvas()) plot_->canvas()->installEventFilter(this); } bool LivePanner::eventFilter(QObject* obj, QEvent* ev) { if (!plot_ || obj != plot_->canvas()) return QObject::eventFilter(obj, ev); switch (ev->type()) { case QEvent::MouseButtonPress: { auto* me = static_cast(ev); if (me->button() == Qt::LeftButton) { panning_ = true; startPos_ = me->pos(); x0Min_ = plot_->axisScaleDiv(xAxis_).lowerBound(); x0Max_ = plot_->axisScaleDiv(xAxis_).upperBound(); y0Min_ = plot_->axisScaleDiv(yAxis_).lowerBound(); y0Max_ = plot_->axisScaleDiv(yAxis_).upperBound(); return true; } break; } case QEvent::MouseMove: { if (!panning_) break; auto* me = static_cast(ev); const int W = plot_->canvas()->width(); const int H = plot_->canvas()->height(); if (W <= 0 || H <= 0) break; const double dxData = (me->pos().x() - startPos_.x()) * (x0Max_ - x0Min_) / W; const double dyData = (me->pos().y() - startPos_.y()) * (y0Max_ - y0Min_) / H; // 拖右(dx>0)→窗口左移(xmin/xmax 减),内容随光标右移; // 拖下(像素 dy>0)→yLeft 数据向上→窗口上移(ymin/ymax 增),内容随光标下移。 plot_->setAxisScale(xAxis_, x0Min_ - dxData, x0Max_ - dxData); plot_->setAxisScale(yAxis_, y0Min_ + dyData, y0Max_ + dyData); plot_->replot(); return true; } case QEvent::MouseButtonRelease: { auto* me = static_cast(ev); if (me->button() == Qt::LeftButton) { panning_ = false; return true; } break; } case QEvent::Wheel: { // 滚轮缩放(以光标为中心,上滚=放大),并 **消费事件**(return true)避免冒泡到外层 // 滚动区域触发滚动条。两轴同因子缩放→保持锁定的真实比尺。 auto* we = static_cast(ev); const int d = we->angleDelta().y(); if (d == 0) return true; const double f = (d > 0) ? (1.0 / 1.15) : 1.15; // 上滚→区间缩小→放大 const QPointF pos = we->position(); const double cx = plot_->invTransform(xAxis_, pos.x()); const double cy = plot_->invTransform(yAxis_, pos.y()); const double xMin = plot_->axisScaleDiv(xAxis_).lowerBound(); const double xMax = plot_->axisScaleDiv(xAxis_).upperBound(); const double yMin = plot_->axisScaleDiv(yAxis_).lowerBound(); const double yMax = plot_->axisScaleDiv(yAxis_).upperBound(); plot_->setAxisScale(xAxis_, cx - (cx - xMin) * f, cx + (xMax - cx) * f); plot_->setAxisScale(yAxis_, cy - (cy - yMin) * f, cy + (yMax - cy) * f); plot_->replot(); we->accept(); return true; } default: break; } return QObject::eventFilter(obj, ev); } } // namespace geopro::app