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));
    }
}
相关推荐
代钦塔拉1 分钟前
第二篇:VS2019 + Qt5.9.9 中文乱码实战:源码GB2312不乱码、文件写入与跨平台方案
开发语言·qt
sycmancia2 小时前
Qt中的事件处理(二)
开发语言·qt
hanbr2 小时前
Qt 进阶开发:主窗口、对话框、布局与常用控件全解析
qt
小短腿的代码世界4 小时前
Qt时间日期处理与QTimer高级应用:从毫秒级精度到跨平台定时器的完整架构解析
开发语言·qt·架构
小短腿的代码世界5 小时前
QGC飞控参数系统架构深度解析:从XML到飞控寄存器的参数同步引擎
qt·microsoft·ui
小短腿的代码世界5 小时前
QGC固件升级与引导加载架构深度解析:从Bootloader握手到固件校验的完整流程
qt·性能优化·架构
buhuizhiyuci5 小时前
【QT-百日筑基篇】打完完怪,开始学炼丹, 前往藏书阁寻找对应材料的信息,并前往去寻找对应材料-QT信号和槽
开发语言·qt
小短腿的代码世界5 小时前
QtitanRibbon深度解析:从微软Office UI到Qt跨平台Ribbon框架的完整架构实现
qt·microsoft·ui
郝学胜-神的一滴5 小时前
CMake 010 :一步到位链接静态库
开发语言·c++·qt·程序人生·系统架构·cmake
Shadow(⊙o⊙)6 小时前
qt中自定义槽函数 内部继承逻辑、GUI+CLI协同1.0
开发语言·前端·c++·qt