Qt触摸屏双指缩放和单指移动界面(支持嵌入式设备)

本文介绍的QGraphicsView的双指缩放,QWidget更简单,可以参考当前内容。

1、首先需要打开触摸屏功能。

this->setAttribute(Qt::WA_AcceptTouchEvents);

2、在event事件管理器中接收触摸屏的三个事件,TouchBegin、TouchUpdate和TouchEnd。

3、判断单点触摸还是多点触摸。

4、如果多点触摸,通过比较前后两次两点间触摸位置来判断是放大还是缩小。

5、多点触摸时,会存在抖动情况,需要做防抖处理。

6、如果是单点触摸,通过比较手指放上去的位置和手指拖动时的位置来设置界面滚动条的位置。

代码:

属性设置

clike 复制代码
    this->setAttribute(Qt::WA_AcceptTouchEvents);

缩放和移动逻辑

clike 复制代码
bool MGraaphicsView::event(QEvent *e)
{
    static int index = 0;
    switch (e->type()) {
    case QEvent::TouchBegin:
    case QEvent::TouchUpdate:
    case QEvent::TouchEnd:
    {
        qDebug() <<"CProjectionPicture::event"<<e->type();
        QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
        QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
        if (touchPoints.count() == 2) {
            //缩放
            const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
            const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();
            qreal currentScaleFactor = QLineF(touchPoint0.pos(), touchPoint1.pos()).length()
                    / QLineF(touchPoint0.startPos(), touchPoint1.startPos()).length();
            if (currentScaleFactor  > _lastScaleFactor)
                index++;
            else if (currentScaleFactor  < _lastScaleFactor)
                index--;
            if (index == 5)//超过5次放大,则认为有效.防抖操作
            {
                index = 0;
                zoomOnce(true);
            }
            else if (index == -5)
            {
                index = 0;
                zoomOnce(false);
            }
            qDebug()<<index<<currentScaleFactor<<_lastScaleFactor;
            _lastScaleFactor = currentScaleFactor;
            update();
        }
        else if (touchPoints.count() == 1)
        {//移动
            const QTouchEvent::TouchPoint &touchPoint = touchPoints.first();
            if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchEnd)
                _startScenePos = mapToScene(touchPoint.pos().toPoint());

            if (e->type() == QEvent::TouchUpdate)
            {
                QPointF endScenePos = mapToScene(touchPoint.pos().toPoint());
                QPointF delta = endScenePos - _startScenePos;
                int oposx = this->horizontalScrollBar()->value();
                int oposy = this->verticalScrollBar()->value();
                int nposx = oposx - delta.x();
                int nposy = oposy - delta.y();
                this->horizontalScrollBar()->setValue(nposx);
                this->verticalScrollBar()->setValue(nposy);
            }

            qDebug()<<"====="<<_startScenePos<<touchPoint.pos();
        }
        if (touchEvent->touchPointStates() & Qt::TouchPointReleased)
        {
            qDebug()<<"Qt::TouchPointReleased";
        }
        return true;//一定不要调QGraphicsView::event(e);否则手指触摸会经常失效
    }
    default:
        break;
    }

    return QGraphicsView::event(e);
}

//缩放

clike 复制代码
void MGraaphicsView::zoomOnce(bool increase)
{
    if (increase)
        setZoom(1);
    else
        setZoom(-1);
}

void MGraaphicsView::setZoom(int val)
{
    if (val > 0)
    {
        m_zoom++;
        auto scaleValue = qPow(2, m_zoom);
        setTransform(QTransform::fromScale(scaleValue, scaleValue));
    }
    else
    {
        m_zoom--;
        auto scaleValue = qPow(2, m_zoom);
        setTransform(QTransform::fromScale(scaleValue, scaleValue));
    }
}
相关推荐
顧棟16 分钟前
【Flink实战】升级HDFS,对Flink SQL(On Yarn模式)的功能兼容性验证
hadoop·flink·1024程序员节
长沙红胖子Qt37 分钟前
VTK开发笔记(八):示例Cone5,交互器的实现方式,在Qt窗口中详解复现对应的Demo
qt·vtk·交互·交互器
2501_938782091 小时前
《Hive 分区裁剪与并行查询:如何让并行任务只处理必要数据》
1024程序员节
使者大牙1 小时前
释放内存与加速推理:PyTorch的torch.no_grad()与torch.inference_mode()
1024程序员节
mailangduoduo2 小时前
残差网络的介绍及ResNet-18的搭建(pytorch版)
人工智能·深度学习·残差网络·卷积神经网络·分类算法·1024程序员节
不去幼儿园4 小时前
【启发式算法】狼群算法(WPA)与灰狼算法(GWO)轻解
1024程序员节
前端 贾公子5 小时前
手写 Vuex4 源码(上)
1024程序员节
青鱼入云5 小时前
redisson介绍
redis·1024程序员节
Forever_Hopeful6 小时前
数据结构:C 语言实现 408 链表真题:解析、拆分、反转与交替合并
1024程序员节
APIshop7 小时前
阿里巴巴 1688 API 接口深度解析:商品详情与按图搜索商品(拍立淘)实战指南
1024程序员节