4. 手势识别入门

在 Qt Quick 的触摸交互体系中,GestureArea、PinchArea 和 PanArea 是三个最常被初学者接触的手势处理元素。它们分别面向“离散手势识别”“双指缩放旋转”“单指平移拖动”三类典型场景。理解它们的职责边界、信号触发条件以及坐标系统,是后续实现复杂多点触控交互的基础。

本节核心目标:能根据交互意图正确选择 GestureArea、PinchArea 或 PanArea,并掌握其基础信号与属性配置。

一、三者的定位与核心原理

Qt Quick 中的手势处理并不是“一个元素包打天下”,而是按手势类型拆分为不同元素。它们都继承自 Item,通过覆盖在目标可视元素之上来捕获触摸事件,再把识别结果以信号形式抛出。

  • GestureArea:用于识别系统预定义的离散手势,例如轻点、长按、滑动、捏合等。它通过 gesture 属性指定要识别的手势类型,适合“一次触发、一次响应”的交互。
  • PinchArea:专门处理双指捏合与旋转。它提供 pinchStarted、pinchUpdated、pinchFinished 三个信号,并暴露 pinch.scale、pinch.rotation、pinch.center 等实时参数,适合图片缩放、地图旋转等连续变换。
  • PanArea:专门处理单指或多指平移拖动。它通过 panStarted、panUpdated、panFinished 信号报告拖动过程,并给出 pan.delta、pan.position 等数据,适合内容滚动、画布拖拽。

三者的共同点是:都依赖触摸事件流,都需要放置在可交互区域上方,并且都通过信号驱动业务逻辑。区别在于识别的手势形态、参数粒度和适用场景不同。

Qt Quick 手势识别元素分工 按手势形态选择元素,通过信号驱动交互逻辑 GestureArea 离散手势识别 Tap / LongPress Swipe / Pinch gesture 属性指定类型 onGesture 信号 适合:按钮点击、 长按菜单、快速滑动 一次触发,一次响应 PinchArea 双指缩放与旋转 pinch.scale pinch.rotation pinch.center pinchUpdated 适合:图片缩放、 地图旋转、画布变换 连续更新,实时反馈 PanArea 单指/多指平移 pan.delta pan.position pan.active panUpdated 适合:内容滚动、 画布拖拽、列表滑动 连续更新,位移驱动 互补 互补 选择原则:离散手势用 GestureArea,双指变换用 PinchArea,平移拖动用 PanArea

二、基础用法与信号流程

三个元素的使用方式高度一致:先声明元素,再绑定信号,最后在信号处理函数中读取参数并更新界面。下面分别给出最小可用示例。

1. GestureArea 基础用法

import QtQuick 2.15

Rectangle {
    width: 300; height: 200
    color: "#eaf2ff"

    GestureArea {
        anchors.fill: parent
        gesture: GestureArea.Tap
        onGesture: {
            console.log("轻点触发,位置:", gesture.position)
        }
    }
}

gesture 属性决定识别哪种手势,常见取值包括 Tap、LongPress、Swipe、Pinch 等。当手势被识别后,onGesture 信号处理函数会被调用,并可通过 gesture 对象读取位置、方向等参数。

2. PinchArea 基础用法

import QtQuick 2.15

Image {
    id: photo
    source: "photo.jpg"
    width: 300; height: 300
    scale: 1.0
    rotation: 0

    PinchArea {
        anchors.fill: parent
        pinch.target: photo
        pinch.minimumScale: 0.5
        pinch.maximumScale: 3.0

        onPinchUpdated: {
            photo.scale = pinch.scale
            photo.rotation = pinch.rotation
        }
    }
}

pinch.target 可以直接指定被变换的目标元素,Qt Quick 会自动应用缩放和旋转。若需要自定义变换逻辑,则可在 onPinchUpdated 中手动读取 pinch.scale 和 pinch.rotation。

3. PanArea 基础用法

import QtQuick 2.15

Rectangle {
    id: canvas
    width: 400; height: 300
    color: "#fff4e6"

    Rectangle {
        id: box
        width: 80; height: 80
        color: "#f59e42"
        x: 100; y: 100
    }

    PanArea {
        anchors.fill: parent
        onPanUpdated: {
            box.x += pan.delta.x
            box.y += pan.delta.y
        }
    }
}

pan.delta 表示本次更新相对于上一次的位移增量,因此使用 += 累加即可实现平滑拖动。若直接赋值 pan.position,则会把元素位置重置为手指绝对坐标,通常不是期望行为。

三、参数与信号对比清单

元素 核心信号 关键参数 典型场景 触发特征
GestureArea onGesture gesture.position、gesture.direction 轻点、长按、快速滑动 离散,一次触发
PinchArea pinchStarted / pinchUpdated / pinchFinished pinch.scale、pinch.rotation、pinch.center 图片缩放、地图旋转 连续,双指驱动
PanArea panStarted / panUpdated / panFinished pan.delta、pan.position、pan.active 内容滚动、画布拖拽 连续,位移驱动

四、常见误区与复盘建议

误区一:用 PanArea 处理双指缩放。 PanArea 只报告平移位移,不提供缩放和旋转参数。双指变换应使用 PinchArea,否则会出现“手指分开但元素不缩放”的问题。
误区二:在 onPanUpdated 中直接赋值 pan.position。 pan.position 是手指在父坐标系中的绝对位置,直接赋值会导致元素“跳”到手指下方。正确做法是累加 pan.delta。
复盘建议: 先明确交互意图属于“离散触发”还是“连续变换”,再决定使用哪个元素。若同时需要平移和缩放,可以叠加 PanArea 与 PinchArea,但要注意事件竞争与层级顺序。

掌握这三个元素后,你已经可以覆盖大多数基础触摸交互场景。后续更复杂的手势组合、事件拦截与自定义识别,都建立在对这三者信号模型和坐标系统的准确理解之上。