实现QtCharts曲线图移动和缩放:
继承QChartView,主要重新实现鼠标事件和键盘事件。
实现移动
CSDN QT技术栈大纲:Qt开发必备技术栈学习路线和资料
- 1 void ChartView::mousePressEvent(QMouseEvent *event)
- 2 {
- 3 if (event->button() == Qt::LeftButton)
- 4 {
- 5 m_lastPoint = event->pos();
- 6 m_isPress = true;
- 7 }
- 8 }
- 9
- 10 void ChartView::mouseMoveEvent(QMouseEvent *event)
- 11 {
- 12 if (!m_coordItem)
- 13 {
- 14 m_coordItem = new QGraphicsSimpleTextItem(this->chart());
- 15 m_coordItem->setZValue(5);
- 16 m_coordItem->setPos(100, 60);
- 17 m_coordItem->show();
- 18 }
- 19 const QPoint curPos = event->pos();
- 20 QPointF curVal = this->chart()->mapToValue(QPointF(curPos));
- 21 QString coordStr = QString("X = %1, Y = %2").arg(curVal.x()).arg(curVal.y());
- 22 m_coordItem->setText(coordStr);
- 23
- 24 if (m_isPress)
- 25 {
- 26 QPoint offset = curPos - m_lastPoint;
- 27 m_lastPoint = curPos;
- 28 if (!m_alreadySaveRange)
- 29 {
- 30 this->saveAxisRange();
- 31 m_alreadySaveRange = true;
- 32 }
- 33 this->chart()->scroll(-offset.x(), offset.y());
- 34 }
- 35 }
- 36
- 37 void ChartView::mouseReleaseEvent(QMouseEvent *event)
- 38 {
- 39 m_isPress = false;
- 40 if (event->button() == Qt::RightButton)
- 41 {
- 42 if (m_alreadySaveRange)
- 43 {
- 44 this->chart()->axisX()->setRange(m_xMin, m_xMax);
- 45 this->chart()->axisY()->setRange(m_yMin, m_yMax);
- 46 }
- 47 }
- 48 }
- 49
- 50 //保存原始位置
- 51 void ChartView::saveAxisRange()
- 52 {
- 53 QValueAxis *axisX = dynamic_cast<QValueAxis*>(this->chart()->axisX());
- 54 m_xMin = axisX->min();
- 55 m_xMax = axisX->max();
- 56 QValueAxis *axisY = dynamic_cast<QValueAxis*>(this->chart()->axisY());
- 57 m_yMin = axisY->min();
- 58 m_yMax = axisY->max();
- 59 }
实现缩放
- 1 void ChartView::wheelEvent(QWheelEvent *event)
- 2 {
- 3 const QPoint curPos = event->pos();
- 4 QPointF curVal = this->chart()->mapToValue(QPointF(curPos));
- 5
- 6 if (!m_alreadySaveRange)
- 7 {
- 8 this->saveAxisRange();
- 9 m_alreadySaveRange = true;
- 10 }
- 11 const double factor = 1.5;//缩放比例
- 12 if (m_ctrlPress)
- 13 {//Y轴
- 14 QValueAxis *axisY = dynamic_cast<QValueAxis*>(this->chart()->axisY());
- 15 const double yMin = axisY->min();
- 16 const double yMax = axisY->max();
- 17 const double yCentral = curVal.y();
- 18
- 19 double bottomOffset;
- 20 double topOffset;
- 21 if (event->delta() > 0)
- 22 {//放大
- 23 bottomOffset = 1.0 / factor * (yCentral - yMin);
- 24 topOffset = 1.0 / factor * (yMax - yCentral);
- 25 }
- 26 else
- 27 {//缩小
- 28 bottomOffset = 1.0 * factor * (yCentral - yMin);
- 29 topOffset = 1.0 * factor * (yMax - yCentral);
- 30 }
- 31
- 32 this->chart()->axisY()->setRange(yCentral - bottomOffset, yCentral + topOffset);
- 33 }
- 34 else
- 35 {//X轴
- 36 QValueAxis *axisX = dynamic_cast<QValueAxis*>(this->chart()->axisX());
- 37 const double xMin = axisX->min();
- 38 const double xMax = axisX->max();
- 39 const double xCentral = curVal.x();
- 40
- 41 double leftOffset;
- 42 double rightOffset;
- 43 if (event->delta() > 0)
- 44 {//放大
- 45 leftOffset = 1.0 / factor * (xCentral - xMin);
- 46 rightOffset = 1.0 / factor * (xMax - xCentral);
- 47 }
- 48 else
- 49 {//缩小
- 50 leftOffset = 1.0 * factor * (xCentral - xMin);
- 51 rightOffset = 1.0 * factor * (xMax - xCentral);
- 52 }
- 53 this->chart()->axisX()->setRange(xCentral - leftOffset, xCentral + rightOffset);
- 54 }
- 55 }
- 56 }
要使用手势,先在构造函数中注册允许使用手势
- 1 //this->setAttribute(Qt::WA_AcceptTouchEvents); //设置接收触摸事件
- 2 grabGesture(Qt::PinchGesture); //这里只grabGesture了PinchGesture
- 1 //监听事件类型
- 2 bool ChartView::event(QEvent *event)
- 3 {
- 4 switch(event->type())
- 5 {
- 6 // case QEvent::TouchBegin:
- 7 // //accepting touch begin allows us to get touch updates
- 8 // return true;
- 9 // break;
- 10 case QEvent::Gesture: //如果是手势事件就交给手势事件处理
- 11 return gestureEvent(static_cast<QGestureEvent*>(event));
- 12 break;
- 13 default: //默认为鼠标事件
- 14 break;
- 15 }
- 16 return QWidget::event(event);
- 17 }
- 18
- 19 //处理手势事件
- 20 bool ChartView::gestureEvent(QGestureEvent *event)
- 21 {
- 22 if (!m_alreadySaveRange) //执行手势事件之前先保存原始位置
- 23 {
- 24 this->saveAxisRange();
- 25 m_alreadySaveRange = true;
- 26 }
- 27
- 28 if (QGesture *pinch = event->gesture(Qt::PinchGesture)) //如果是捏合手势,进行缩放处理
- 29 {
- 30 pinchTriggered(static_cast<QPinchGesture *>(pinch));
- 31 event->accept();
- 32 }
- 33 return true;
- 34 }
- 35
- 36 //处理缩放事件
- 37 void ChartView::pinchTriggered(QPinchGesture *gesture)
- 38 {
- 39 QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
- 40 if (changeFlags & QPinchGesture::ScaleFactorChanged)
- 41 {
- 42 currentStepScaleFactor = gesture->scaleFactor(); //合计放大系数
- 43 }
- 44 if (gesture->state() == Qt::GestureFinished)
- 45 {
- 46 scaleFactor = 1;
- 47 scaleFactor *= currentStepScaleFactor;
- 48 currentStepScaleFactor = 1;
- 49 }
- 50
- 51 if(scaleFactor >= 1)
- 52 {
- 53 this->chart()->zoom(1.05);
- 54 }
- 55 else if(scaleFactor < 1)
- 56 {
- 57 this->chart()->zoom(0.95);
- 58 }
- 59 update();
- 1 #pragma once
- 2
- 3 #include <QChartView>
- 4 #include <QMouseEvent>
- 5 #include <QGraphicsSimpleTextItem>
- 6
- 7 QT_CHARTS_USE_NAMESPACE
- 8
- 9 class ChartView : public QChartView
- 10 {
- 11 Q_OBJECT
- 12
- 13 public:
- 14 ChartView(QChart *chart, QWidget *parent = nullptr);
- 15 ~ChartView();
- 16 // 保存坐标区域,用于复位
- 17 void saveAxisRange();
- 18
- 19 protected:
- 20 void mousePressEvent(QMouseEvent *event);
- 21 void mouseMoveEvent(QMouseEvent *event);
- 22 void mouseReleaseEvent(QMouseEvent *event);
- 23 void wheelEvent(QWheelEvent *event);
- 24 void keyPressEvent(QKeyEvent *event);
- 25 void keyReleaseEvent(QKeyEvent *event);
- 26
- 27 //以下3个为Qt Android下Qchart的缩放(单指触点时默认为鼠标点击,所以移动功能可正常使用)
- 28 bool event(QEvent *event) override; //使用手势实现缩放
- 29 bool gestureEvent(QGestureEvent *event);
- 30 void pinchTriggered(QPinchGesture *gesture);
- 31
- 32 private:
- 33 QPoint m_lastPoint;
- 34 bool m_isPress;
- 35 bool m_ctrlPress;
- 36 bool m_alreadySaveRange;
- 37 double m_xMin, m_xMax, m_yMin, m_yMax;
- 38 QGraphicsSimpleTextItem* m_coordItem;
- 39 };
- 1 #include <QApplication>
- 2 #include <QMainWindow>
- 3 #include <QLineSeries>
- 4 #include "ChartView.h"
- 5
- 6 int main(int argc, char *argv[])
- 7 {
- 8 QApplication a(argc, argv);
- 9
- 10 QLineSeries *series = new QLineSeries();
- 11
- 12
- 13 series->append(0, 6);
- 14 series->append(2, 4);
- 15 series->append(3, 8);
- 16 series->append(7, 4);
- 17 series->append(10, 5);
- 18 *series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2);
- 19
- 20 QChart *chart = new QChart();
- 21 chart->legend()->hide();
- 22 chart->addSeries(series);
- 23 chart->createDefaultAxes();
- 24 chart->setTitle("图形移动和缩放");
- 25
- 26 auto *chartView = new ChartView(chart);//使用自定义ChartView
- 27 chartView->setRenderHint(QPainter::Antialiasing);
- 28
- 29 QMainWindow window;
- 30 window.setCentralWidget(chartView);
- 31 window.resize(400, 300);
- 32 window.show();
- 33
- 34 return a.exec();
- 35 }
- 1 QT += core gui charts
- 2
- 3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
- 4
- 5 CONFIG += c++11
- 6
- 7 # The following define makes your compiler emit warnings if you use
- 8 # any Qt feature that has been marked deprecated (the exact warnings
- 9 # depend on your compiler). Please consult the documentation of the
- 10 # deprecated API in order to know how to port your code away from it.
- 11 DEFINES += QT_DEPRECATED_WARNINGS
- 12
- 13 # You can also make your code fail to compile if it uses deprecated APIs.
- 14 # In order to do so, uncomment the following line.
- 15 # You can also select to disable deprecated APIs only up to a certain version of Qt.
- 16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
- 17
- 18 SOURCES += \
- 19 ChartView.cpp \
- 20 main.cpp
- 21
- 22 HEADERS += \
- 23 ChartView.h
- 24
- 25 FORMS +=
- 26
- 27 # Default rules for deployment.
- 28 qnx: target.path = /tmp/$${TARGET}/bin
- 29 else: unix:!android: target.path = /opt/$${TARGET}/bin
- 30 !isEmpty(target.path): INSTALLS += target
ps:将文件都放在这,下次要用可以直接来复制,方便点。
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓