Qt for android下通过手势事件对Chart曲线图缩放和平移的实现

一、功能要求

  对Qt5.14开发的手机APP中绘制的曲线,进行触摸操作,实现对曲线的缩放和坐标轴平移,还需实现缩放和平移后的坐标复原。

二、实现过程

实现过程总体比较曲折,具体如下:

第一次:参考例子程序zoomlinechart,采用event,gestureEvent以及mousePressEvent、mouseMoveEvent、mouseReleaseEvent实现,但是发现存在两个问题:

1)只识别到PinchGesture,通过“捏”动作实现Chart图缩放,但是不能检测到panGesture,无法按照例程中的实现Chart图平移

2)在ChartView内点击,只检测到mousePressEvent,无法检测到mouseMoveEvent、mouseReleaseEvent,即无法在Chart图上拖动实现平移,但是只能在ChartView外窗口的区域才能实现Chart图平移,在Chart图上双击可以坐标复原。

第二次:又通过setAcceptTouchEvent设置接收触摸事件,但是发现窗口内Chart图下面的保存按钮和画面关闭按钮不起作用了;

第三次:通过网上查找资料了解到,在Android或linux下,存在无法检测到单指移动的panGetureEvent事件,而不像在例程说明中的是基于windows系统的情况,Stackoverflow网站https://stackoverflow.com/questions/49287314/qgestureevent-for-mouse

的介绍,通过手势识别器panGestureRecognizer()来识别panGesture,将网站的程序复制到项目中,编译后出现运行崩溃的问题,注释掉panGestureRecognizer::create(Object *target)函数,再没有出现程序崩溃的情况,但是触摸后没有任何反应,程序中的qDebug()也没有显示出检测到panGesture程序的执行。

最后:通过网上查找资料了解到,QGraphicsView的对象有mouseEvent事件,再次对例子程序zoomlinechart阅读发现,程序中单独新建了一个ChartView类,而没用系统的QchartView类,在Chartview下的protected内建有mousePressEvent,mouseMoveEvent,mouseMoveEvent等事件,事件函数内最后一句:return QChartView::mouseMoveEvent(event);也表明了不同于我第一次在程序中将此句只能写成的:return QWidget::mouseMoveEvent(event);,也就解释了为什么在ChartView内mouseMoveEvent和mouseReleaseEvent动作检测不到,而只能在ChartView外窗口的区域检测到的原因。

三、程序

.h文件程序:

#ifndef PITCHTRAJECTORY_H
#define PITCHTRAJECTORY_H

#include <QWidget>
#include <QToolButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFormLayout>
#include <QGridLayout>
#include <QFileDialog>
#include <QStandardPaths>
#include <QAbstractItemView>
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>    //用于创建折线图
#include <QtCharts/QSplineSeries>  //用于创建曲线图
#include <QtCharts/QValueAxis>   //创建坐标轴
#include <QtCharts/QCategoryAxis>
#include <QSvgGenerator>
#include <QtWidgets/QGesture>
#include <QtWidgets/QGraphicsScene>
#include <QtWidgets/QGraphicsView>
#include <QPointF>


QT_BEGIN_NAMESPACE
class QGestureEvent;
class ChartView;
QT_END_NAMESPACE


QT_CHARTS_USE_NAMESPACE
class pitchtrajectoryshow : public QWidget
{
    Q_OBJECT

public:
  explicit  pitchtrajectoryshow(QWidget *parent = nullptr);
    ~pitchtrajectoryshow();

    QValueAxis *axisX1;
    QValueAxis *axisY1;
    QChart *chart1;
    QSplineSeries *series_deepopenholepitch;
    QSplineSeries *series_deeppitch;
  // QChartView  *chartview1;
    ChartView *chartview1;
    QString charfileName1;


private:
   QToolButton *closechartsBtn;
   QToolButton *savechartsBtn;
   QHBoxLayout *pitchtrajectoryshowLayout1;
   QVBoxLayout *pitchtrajectoryshowLayout;


   qreal scaleFactor=1;
   qreal currentStepScaleFactor=1;
   /* qreal horizontalOffset=0;
   qreal verticalOffset=0;
   Qt::MouseButton m_translateButton=Qt::LeftButton;  // 平移按钮
   bool m_bMouseTranslate=false;
   qreal m_zoomDelta=0.2;  // 缩放的增量
   QPoint m_lastMousePos;  // 鼠标最后按下的位置*/


   bool gestureEvent(QGestureEvent *event);
   void pinchTriggered(QPinchGesture*);
   void panTriggered(QPanGesture*);


protected:
     void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
     bool event(QEvent *event) Q_DECL_OVERRIDE;

public slots:
   void deeppitchcharts_Recv(QString fileName,QSplineSeries *series0_0,QSplineSeries *series1);
   void deltadata_Recv(qreal horizontalOffset,qreal verticalOffset);

protected slots:
    void closechartsBtn_clicked();
    void savechartsBtn_clicked();

signals:
   void closepitchchartssignal_Send(void);


};

//新建ChartView类

class ChartView : public QChartView
{
     Q_OBJECT
public:
    ChartView(QChart *chart, QWidget *parent = 0);

    Qt::MouseButton m_translateButton=Qt::LeftButton;  // 平移按钮
    bool m_bMouseTranslate=false;
    QPoint m_lastMousePos;  // 鼠标最后按下的位置
    qreal horizontalOffset=0;
    qreal verticalOffset=0;
protected:

    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

signals:
      void deltadata_Send(qreal horizontalOffset,qreal verticalOffset);

};

#endif // PITCHTRAJECTORY_H
.cpp文件:
bool pitchtrajectoryshow::event(QEvent *event)
{
    if (event->type() == QEvent::Gesture)
        return gestureEvent(static_cast<QGestureEvent*>(event));
    return QWidget::event(event);
}

void pitchtrajectoryshow::mouseDoubleClickEvent(QMouseEvent *)
{
    qDebug()<<"识别到鼠标双击动作!";

    //重新复位大小
    chart1->zoomReset();
    chart1->axisX()->setRange(0, 30);
    chart1->axisY()->setRange(-10, 10);
    scaleFactor = 1;
    currentStepScaleFactor = 1;
    chartview1->verticalOffset=0;
    chartview1->horizontalOffset=0;
    chartview1->m_bMouseTranslate=false;
    update();
}

bool pitchtrajectoryshow::gestureEvent(QGestureEvent *event)
{
    qDebug() << "gestureEvent():" << event->gestures().size();
    if (QGesture *pan = event->gesture(Qt::PanGesture))
        panTriggered(static_cast<QPanGesture *>(pan));
    if (QGesture *pinch = event->gesture(Qt::PinchGesture))
        pinchTriggered(static_cast<QPinchGesture *>(pinch));
    return true;
}

void pitchtrajectoryshow::panTriggered(QPanGesture *gesture)
{
   qDebug()<<"识别到手势pan动作!";
 #ifndef QT_NO_CURSOR
    switch (gesture->state())
    {
    case Qt::GestureStarted:
    case Qt::GestureUpdated:
        setCursor(Qt::SizeAllCursor);
        break;
    default:
        setCursor(Qt::ArrowCursor);
    }
#endif
    QPointF delta = gesture->delta();
   chartview1->horizontalOffset += delta.x();
   chartview1->verticalOffset += delta.y();

    //平移
    chart1->scroll(chartview1->horizontalOffset, chartview1->verticalOffset);
    update();
}

void pitchtrajectoryshow::pinchTriggered(QPinchGesture *gesture)
{
    qDebug()<<"识别到手势pinch动作!";
    QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
    if (changeFlags & QPinchGesture::ScaleFactorChanged)
    {
        currentStepScaleFactor = gesture->totalScaleFactor();
    }
    if (gesture->state() == Qt::GestureFinished)
    {
        scaleFactor *= currentStepScaleFactor;
        currentStepScaleFactor = 1;
    }

    //缩放
    chart1->zoom(scaleFactor); //缩放
    update();
}

void pitchtrajectoryshow::deltadata_Recv(qreal horizontalOffset,qreal verticalOffset)
{
     chart1->scroll(horizontalOffset, verticalOffset);
     update();
}




void ChartView::mouseMoveEvent(QMouseEvent *event)
{
      qDebug()<<"识别到鼠标移动动作!";
    if (m_bMouseTranslate)
    {
        QPointF mouseDelta = event->pos() - m_lastMousePos;
        horizontalOffset += mouseDelta.x();
        verticalOffset += mouseDelta.y();
        emit deltadata_Send(horizontalOffset,verticalOffset);
    }
    m_lastMousePos = event->pos();
    QChartView::mouseMoveEvent(event);

}

void ChartView::mousePressEvent(QMouseEvent *event)
{

       qDebug()<<"识别到鼠标压下动作!";
     if (event->button() == m_translateButton)
     {
         m_bMouseTranslate = true;
         m_lastMousePos = event->pos();
         setCursor(Qt::OpenHandCursor);
     }
    // QWidget::mousePressEvent(event);
     QChartView::mousePressEvent(event);
}
void ChartView::mouseReleaseEvent(QMouseEvent *event)
{
      qDebug()<<"识别到鼠标释放动作!";
    if (event->button() == m_translateButton)
    {
        m_bMouseTranslate = false;
        setCursor(Qt::ArrowCursor);
    }
  // QWidget::mouseReleaseEvent(event);
   QChartView::mouseReleaseEvent(event);
}
曲线界面:

四、小结

1、通过pitchtrajectoryshow窗口下PinchGesture动作事件识别,触发函数下: chart1->zoom(scaleFactor),实现图片的缩放;

2、通过ChartView下mousePressEvent、mouseMoveEvent、mouseReleasesEvent动作识别,在函数void pitchtrajectoryshow::deltadata_Recv(qreal horizontalOffset,qreal verticalOffset)  中实现平移量数据的接收,chart1->scroll(horizontalOffset, verticalOffset); 实现chartView内chart曲线的平移

3、通过pitchtrajectoryshow窗口下mouseDoubleClickEvent事件, chart1->zoomReset(); chart1->axisX()->setRange(0, 30);chart1->axisY()->setRange(-10, 10);将chart坐标复原。

 
  
 
    
 
 
  
 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
qt for android中的触摸手势事件QGestureEvent是用于处理多点触摸手势事件Android设备上的触摸事件可以包含更复杂的手势,如双指缩放、双击、长按等。QGestureEvent提供了一种简单且方便的方式来处理这些手势事件。 QGestureEvent类继承自QEvent类,用于描述手势事件。通过QGestureEvent,我们可以获取触摸手势的各种信息,如手势类型、触摸点数、手势状态等。 Qt提供了一些与手势事件相关的类,如QPanGesture、QPinchGesture、QSwipeGesture等,用于表示不同类型的手势。在处理QGestureEvent时,我们可以通过QGestureEvent的gestures()方法获取触发的手势对象列表,然后根据手势对象的类型来判断具体的手势类型,并进行相应的处理。 在使用QGestureEvent处理手势事件时,首先需要在相关的widget或view上开启手势事件的接收,可以通过设置setAcceptedGestures()方法来指定接收哪些手势。然后,在手势事件触发时,会自动调用widget或view的gestureEvent()方法来处理手势事件。 QGestureEvent提供了一些便捷的方法来获取手势事件的更详细信息,如gestureType()可以获取手势的类型,state()可以获取手势的状态,gesture()可以获取具体的手势对象等。 总之,通过QGestureEvent和相关的手势类,我们可以方便地实现多点触摸手势的处理。在Qt for Android中,使用QGestureEvent可以更好地响应和处理复杂的手势事件,提升用户体验和交互性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值