QtCharts图形移动和缩放

功能

实现QtCharts曲线图移动和缩放:

  1. 按住鼠标左键拖动曲线可移动曲线;
  2. 滚动鼠标滚轮实现图形X轴方向的缩放;
  3. 安装Ctrl,滚动鼠标滚轮实现图形Y轴方向的缩放;
  4. 按鼠标右键恢复图形初始状态;
  5. 缩放过程以鼠标当前位置为缩放中心;
  6. 鼠标移动过程中会在左上角显示当前坐标。

实现

继承QChartView,主要重新实现鼠标事件和键盘事件。

  1. 移动图形利用QChart的scroll函数;
    void scroll(qreal dx, qreal dy, const QRectF &rect = QRectF());
    鼠标按下时,记录按下状态,并记录当前坐标位置,在移动事件内计算鼠标移动的距离,以此设置图形滚动的距离,即可实现移动
  2. 缩放则设置当前坐标轴的显示范围;
    void setRange(const QVariant &min, const QVariant &max);

核心代码

  1. 实现移动
void ChartView::mousePressEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton) {
        prevPoint_ = event->pos();
        leftButtonPressed_ = true;
	}
}

void ChartView::mouseMoveEvent(QMouseEvent *event)
{
	if (!coordItem_) {
		coordItem_ = new QGraphicsSimpleTextItem{ chart() };
		coordItem_->setZValue(5);
		coordItem_->setPos(100, 60);
		coordItem_->show();
	}
	const QPoint curPos{ event->pos() };
	const QPointF curVal{ chart()->mapToValue(QPointF(curPos)) };
	coordItem_->setText(QString("X = %1, Y = %2").arg(curVal.x()).arg(curVal.y()));

	if (leftButtonPressed_) {
		const auto offset = curPos - prevPoint_;
		prevPoint_ = curPos;
		if (!alreadySaveRange_) {
			saveAxisRange();
			alreadySaveRange_ = true;
		}
		chart()->scroll(-offset.x(), offset.y());
	}
}

void ChartView::mouseReleaseEvent(QMouseEvent *event)
{
	leftButtonPressed_ = false;
	if (event->button() == Qt::RightButton) {
		if (alreadySaveRange_) {
            chart()->axisX()->setRange(xRange_[0], xRange_[1]);
            chart()->axisY()->setRange(yRange_[0], yRange_[1]);
		}
	}
}
  1. 实现缩放
void ChartView::wheelEvent(QWheelEvent *event)
{
#if (QT_VERSION <= QT_VERSION_CHECK(6,0,0))
   const auto pos  = QPointF(event->pos());
   const auto isZoomIn = event->delta() > 0;
#else
   const auto pos  = event->position();
   const auto isZoomIn = event->angleDelta().y() > 0;
#endif
   const QPointF curVal = chart()->mapToValue(pos);

   if (!alreadySaveRange_) {
   	saveAxisRange();
   	alreadySaveRange_ = true;
   }

   auto zoom = [](QValueAxis* axis, double centre, bool zoomIn) {
   	constexpr auto scaling{ 1.5 };

   	const double down = axis->min();
   	const double up = axis->max();

   	double downOffset{};
   	double upOffset{};
   	if (zoomIn) {
   		downOffset = (centre - down) / scaling;
   		upOffset = (up - centre) / scaling;
   	}
   	else {
   		downOffset = (centre - down) * scaling;
   		upOffset = (up - centre) * scaling;
   	}

   	axis->setRange(centre - downOffset, centre + upOffset);
   };
   
   if (ctrlPressed_) {
   	auto axis = qobject_cast<QValueAxis*>(chart()->axisY());
   	zoom(axis, curVal.y(), isZoomIn);
   } else {
   	auto axis = qobject_cast<QValueAxis*>(chart()->axisX());
   	zoom(axis, curVal.x(), isZoomIn);
   }
}

完整代码和示例程序请在QtCharts图形移动和缩放或 Github下载。

你可能感兴趣的:(Qt,c++,qt)