geopro/src/app/panels/chart/LivePanner.cpp

83 lines
3.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "panels/chart/LivePanner.hpp"
#include <QEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <qwt_plot.h>
#include <qwt_scale_div.h>
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<QMouseEvent*>(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<QMouseEvent*>(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<QMouseEvent*>(ev);
if (me->button() == Qt::LeftButton) {
panning_ = false;
return true;
}
break;
}
case QEvent::Wheel: {
// 滚轮缩放(以光标为中心,上滚=放大),并 **消费事件**return true避免冒泡到外层
// 滚动区域触发滚动条。两轴同因子缩放→保持锁定的真实比尺。
auto* we = static_cast<QWheelEvent*>(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