PinchHandler QML Type

捏合手势的处理程序。更多

Import Statement: import QtQuick
Inherits:

MultiPointHandler

属性

信号

详细说明

PinchHandler 是一个处理程序,用于解释多指手势,以交互方式旋转、缩放和拖动一个 Item。与其他输入处理程序一样,默认情况下它功能齐全,可操作其目标,即声明它的项目。

import QtQuick

Rectangle {
    width: 400
    height: 300
    color: "lightsteelblue"
    PinchHandler { }
}

它具有限制拖动、旋转和缩放范围的属性。

如果它被声明在一个 Item 内,但被分配了一个不同的目标,那么它会处理外部 Item 边界内的事件,但会操作target Item:

import QtQuick

Item {
    width: 640
    height: 480

    Rectangle {
        id: map
        color: "aqua"
        width: 400
        height: 300
    }

    PinchHandler {
        target: map
    }
}

第三种使用方法是将目标设置为null ,并以其他方式对属性变化做出反应:

import QtQuick

Window {
    width: 320; height: 240
    visible: true
    title: handler.persistentRotation.toFixed(1) + "° " +
           handler.persistentTranslation.x.toFixed(1) + ", " +
           handler.persistentTranslation.y.toFixed(1) + " " +
           (handler.persistentScale * 100).toFixed(1) + "%"

    PinchHandler {
        id: handler
        target: null
        persistentScale: 0.25
        onTranslationChanged: (delta) => {
            image.x -= delta.x
            image.y -= delta.y
        }
    }

    Image {
        id: image
        source: "images/album-cover.jpg"
        scale: handler.persistentScale
        x: -600; y: -450
    }
}

注: 当按下的手指数在minimumPointCountmaximumPointCount 之间(含)时,捏合开始。在此之前,PinchHandler 会跟踪任何按下手指的位置,但如果是不允许的数字,则不会缩放或旋转目标active 属性仍为false

另请参阅 PinchArea,QPointerEvent::pointCount(),QNativeGestureEvent::fingerCount() 和Qt Quick 示例 - 指针处理程序

属性文档

acceptedDevices : flags

可激活该指针处理程序的指向设备类型。

默认情况下,该属性设置为PointerDevice.AllDevices 。如果将其设置为设备类型的 OR 组合,则会忽略来自非匹配设备的事件。

例如,可以使用两个处理程序,以一种方式响应鼠标和手写笔点击,以另一种方式响应触摸屏轻触:

Item {
   TapHandler {
       acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
       onTapped: console.log("clicked")
   }
   TapHandler {
       acceptedDevices: PointerDevice.TouchScreen
       onTapped: console.log("tapped")
   }
}

注意: 并非所有平台都能区分鼠标和触摸板;在能区分的平台上,你通常希望鼠标和触摸板的行为相同。


acceptedModifiers : flags

如果设置了该属性,则需要按下给定的键盘修改器才能对指针事件做出反应,否则将忽略它们。

如果该属性设置为Qt.KeyboardModifierMask (默认值),则PointerHandler 会忽略修改键。

例如,Item 可以有两个相同类型的处理程序,其中一个只有在按下所需键盘修饰符时才启用:

Item {
   TapHandler {
       acceptedModifiers: Qt.ControlModifier
       onTapped: console.log("control-tapped")
   }
   TapHandler {
       acceptedModifiers: Qt.NoModifier
       onTapped: console.log("tapped")
   }
}

如果将acceptedModifiers 设置为修改器按键的 OR 组合,则表示必须按下所有这些修改器才能激活处理程序:

Item {
   TapHandler {
       acceptedModifiers: Qt.ControlModifier | Qt.AltModifier | Qt.ShiftModifier
       onTapped: console.log("control-alt-shift-tapped")
   }
}

可用的修改器如下:

常量说明
NoModifier不允许使用任何修改键。
ShiftModifier必须按键盘上的 Shift 键。
ControlModifier必须按键盘上的 Ctrl 键。
AltModifier必须按下键盘上的 Alt 键。
MetaModifier必须按下键盘上的 Meta 键。
KeypadModifier必须按下键盘上的按键。
GroupSwitchModifier仅限 X11(除非在 Windows 上通过命令行参数激活)。必须按下键盘上的模式切换键。
KeyboardModifierMask处理程序并不关心按下了哪些修改器。

如果需要比多个处理程序和多个修改器标志组合更复杂的行为,可以在 JavaScript 代码中检查修改器:

Item {
    TapHandler {
        onTapped:
            switch (point.modifiers) {
            case Qt.ControlModifier | Qt.AltModifier:
                console.log("CTRL+ALT");
                break;
            case Qt.ControlModifier | Qt.AltModifier | Qt.MetaModifier:
                console.log("CTRL+META+ALT");
                break;
            default:
                console.log("other modifiers", point.modifiers);
                break;
            }
    }
}

另请参见 Qt::KeyboardModifier


acceptedPointerTypes : flags

可激活该指针处理程序的指向工具类型(手指、触控笔、橡皮等)。

默认情况下,该属性设置为PointerDevice.AllPointerTypes 。如果将其设置为设备类型的 OR 组合,则会忽略来自非匹配devices 的事件。

例如,可以用两种处理程序使一个控件以某种方式响应鼠标、触摸和手写笔的点击,但如果用绘图板上的橡皮擦工具点击,该控件就会自行删除:

Rectangle {
   id: rect
   TapHandler {
       acceptedPointerTypes: PointerDevice.Generic | PointerDevice.Finger | PointerDevice.Pen
       onTapped: console.log("clicked")
   }
   TapHandler {
       acceptedPointerTypes: PointerDevice.Eraser
       onTapped: rect.destroy()
   }
}

active : bool [read-only]

当所有约束条件(尤其是minimumPointCountmaximumPointCount )都满足且目标(如果有的话)正在被操作时,该属性为true


activeRotation : real [read-only]

捏合手势的旋转角度,单位为度,正值为顺时针方向。手势开始时为0 。如果target不为空,该值将自动添加到rotation 中。否则,可以使用绑定对该值进行任意操作。

另请参阅 QtQuick::PinchHandler::rotationAxis.activeValue


activeScale : real [read-only]

执行捏合手势时的缩放因子。手势开始时的缩放因子为 1.0,随着触摸点的分散而增大,随着触摸点的聚拢而减小。如果target不是空值,scale 将自动乘以该值。否则,可以使用绑定对该值进行任意操作。

另请参阅 QtQuick::PinchHandler::scaleAxis.activeValue


activeTranslation : point [read-only]

执行捏合手势时点群的平移。手势开始时,该值为0, 0 ,随着eventPoint(s) 向下和向右拖动,该值逐渐增大。手势结束后,平移值保持不变;当下一个捏合手势开始时,平移值会重新设置为0, 0

注: 在某些触摸板上,如 macOS 触控板,本机手势不会生成任何平移值,该属性将保持在(0, 0)


centroid : QtQuick::handlerPoint [read-only]

当前按下的触摸点中间的一个点。目标将围绕该点旋转。


cursorShape : Qt::CursorShape

当鼠标悬停在parent 项目上时,该属性会显示光标形状,同时activetrue

可用的光标形状有

  • Qt.ArrowCursor
  • Qt.UpArrowCursor
  • Qt.CrossCursor
  • Qt.WaitCursor
  • Qt.IBeamCursor
  • Qt.SizeVerCursor
  • Qt.SizeHorCursor
  • Qt.SizeBDiagCursor
  • Qt.SizeFDiagCursor
  • Qt.SizeAllCursor
  • Qt.BlankCursor
  • Qt.SplitVCursor
  • Qt.SplitHCursor
  • Qt.PointingHandCursor
  • Qt.ForbiddenCursor
  • Qt.WhatsThisCursor
  • Qt.BusyCursor
  • Qt.OpenHandCursor
  • Qt.ClosedHandCursor
  • Qt.DragCopyCursor
  • Qt.DragMoveCursor
  • Qt.DragLinkCursor

默认值未设置,允许cursorparent 项目出现。可通过将该属性设置为未定义来将其重置为相同的初始状态。

注: 当该属性未设置或已设置为undefined 时,如果读取该值,将返回Qt.ArrowCursor

另请参阅 Qt::CursorShapeQQuickItem::cursor() 和HoverHandler::cursorShape


dragThreshold : int

用户必须拖动eventPoint 才能被视为拖动手势的距离(以像素为单位)。

默认值取决于平台和屏幕分辨率。可以通过将其设置为未定义来将其重置为默认值。拖动手势开始时的行为在不同的处理程序中有所不同。


enabled : bool

如果PointerHandler 被禁用,它将拒绝所有事件,也不会发出任何信号。


grabPermissions : flags

当处理程序的逻辑决定接管独占抓取时,或者当处理程序被其他处理程序要求批准接管或取消抓取时,该属性会指定权限。

常数说明
PointerHandler.TakeOverForbidden此处理程序既不从任何类型的项目或处理程序获取抓取权限,也不向其提供抓取权限。
PointerHandler.CanTakeOverFromHandlersOfSameType该处理程序可以从另一个同类处理程序处获取独家抓取权限。
PointerHandler.CanTakeOverFromHandlersOfDifferentType此处理程序可以从任何类型的处理程序获取独占抓取权限。
PointerHandler.CanTakeOverFromItems该处理程序可以从任何类型的项目中获取独占抓取权。
PointerHandler.CanTakeOverFromAnything该处理程序可以从任何类型的项目或处理程序中获取独占抓取权。
PointerHandler.ApprovesTakeOverByHandlersOfSameType该处理程序允许其他同类处理程序使用抓取。
PointerHandler.ApprovesTakeOverByHandlersOfDifferentType该处理程序允许任何类型的处理程序抓取。
PointerHandler.ApprovesTakeOverByItems该处理程序允许任何类型的物品抓取。
PointerHandler.ApprovesCancellation此处理程序允许其抓取设置为空。
PointerHandler.ApprovesTakeOverByAnything该处理程序允许任何类型的项目或处理程序抓取。

默认值为PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything ,允许大多数抓取场景,但也避免了两个 PinchHandler 争夺同一接触点的情况。


margin : real

parent 项目边界以外的余量,在此范围内eventPoint 可以激活此处理程序。例如,在PinchHandler 上,如果target 也是parent ,那么将其设置为至少相当于一般用户手指宽度一半的距离是非常有用的,这样,如果parent 被缩小到非常小的尺寸,仍然可以使用捏合手势。或者,如果基于TapHandler 的按钮放置在屏幕边缘附近,则可用于遵守菲茨定律:即使按钮与屏幕边缘在视觉上相差几个像素,也会对屏幕边缘的鼠标点击做出反应。

默认值为 0。


parent : Item

Item 是处理程序的作用域;也就是在其中声明的项目。处理程序将代表该 Item 处理事件,这意味着如果指针事件中至少有一个eventPoints 出现在该 Item 的内部,那么该指针事件就是相关的。最初target() 是相同的,但可以重新分配。

另请参阅 targetQObject::parent()。


persistentRotation : real

如果目标不是空的,则是要应用于目标的旋转。否则,可以使用绑定对该值进行任意操作。在执行捏合手势时,activeRotation ;手势结束后,该值保持不变;当下一个捏合手势开始时,activeRotation

可以通过设置该属性,使基础旋转与其他处理程序等以其他方式设置的旋转同步。如果直接设置该属性,activeRotation 不会改变,而rotationChanged(0) 则会发出。


persistentScale : real

缩放因子(如果不是空值,则会在目标上自动设置)。否则,可以使用绑定对该值进行任意操作。在执行捏合手势时,它将持续乘以activeScale ;手势结束后,它将保持不变;当下一个捏合手势开始时,它将再次乘以activeScale

可以通过设置该属性,使基础刻度与其他处理程序等以其他方式设置的刻度同步。如果直接设置该属性,activeScale 不会改变,而scaleChanged(1) 会被发送。


persistentTranslation : point

如果目标不是null ,则将应用于目标的翻译。否则,可以使用绑定对该值进行任意操作。在执行捏合手势时,activeTranslation 会不断添加;手势结束后,该值保持不变。

可以通过设置该属性,使基础翻译与其他处理程序等以其他方式设置的翻译同步。如果直接设置该属性,activeTranslation 不会改变,而translationChanged({0, 0}) 会被发出。

注意: 在某些触摸板(如 macOS 触控板)上,本机手势不会生成任何翻译值,因此该属性将保持(0, 0)


rotationAxis group

rotationAxis.activeValue : real [read-only]

rotationAxis.enabled : bool

rotationAxis.maximum : real

rotationAxis.minimum : real

rotationAxis 控制根据触摸点组的旋转设置目标项目 的约束条件。rotation

minimum 是可接受的最小旋转幅度。 是可接受的最大旋转幅度。如果 为 true,则允许旋转。 与 相同。maximum enabled activeValue QtQuick::PinchHandler::activeRotation

activeValueChanged 信号在activeValue 发生变化时发出,以提供变化的增量。这样做的目的是通过多个处理程序增量调整一个属性。

import QtQuick

Rectangle {
    width: 100; height: 100
    color: "lightsteelblue"; antialiasing: true

    PinchHandler {
        id: handler
        target: null
        xAxis.onActiveValueChanged: (delta) => parent.radius -= delta
        yAxis.onActiveValueChanged: (delta) => parent.border.width += delta
        rotationAxis.onActiveValueChanged: (delta) => parent.rotation += delta // add
        scaleAxis.onActiveValueChanged: (delta) => parent.scale *= delta // multiply
    }

    WheelHandler {
        acceptedModifiers: Qt.NoModifier
        property: "rotation"
    }

    WheelHandler {
        acceptedModifiers: Qt.ControlModifier
        property: "scale"
    }
}

注: 该代码段是特意设计的:PinchHandler 已经知道如何移动、缩放和旋转其父项目,但该代码以一种不那么明确的方式实现了不同的行为,以说明如何在特殊情况下使用activeValueChanged


scaleAxis group

scaleAxis.activeValue : real [read-only]

scaleAxis.enabled : bool

scaleAxis.maximum : real

scaleAxis.minimum : real

scaleAxis 是根据触摸点之间的距离控制目标项目 设置的约束条件。scale

minimum 是可接受的最小缩放比例。 是可接受的最大缩放比例。如果 为 true,则允许缩放。 与 相同。maximum enabled activeValue QtQuick::PinchHandler::activeScale

activeValueChanged 信号在activeValue 发生变化时发出,为增量变化提供乘数。这适用于通过多个处理程序增量调整一个属性。

import QtQuick

Rectangle {
    width: 100; height: 100
    color: "lightsteelblue"; antialiasing: true

    PinchHandler {
        id: handler
        target: null
        xAxis.onActiveValueChanged: (delta) => parent.radius -= delta
        yAxis.onActiveValueChanged: (delta) => parent.border.width += delta
        rotationAxis.onActiveValueChanged: (delta) => parent.rotation += delta // add
        scaleAxis.onActiveValueChanged: (delta) => parent.scale *= delta // multiply
    }

    WheelHandler {
        acceptedModifiers: Qt.NoModifier
        property: "rotation"
    }

    WheelHandler {
        acceptedModifiers: Qt.ControlModifier
        property: "scale"
    }
}

注: 该代码段是特意设计的:PinchHandler 已经知道如何移动、缩放和旋转其父项,但该代码以一种不那么明确的方式实现了不同的行为,以说明如何在特殊情况下使用activeValueChanged


target : Item

该处理程序将处理的项目。

默认情况下,它与parent 相同,即处理程序所声明的项。不过,有时也可以将目标设置为不同的项,以便处理一个项中的事件,但操作另一个项;或者将目标设置为null ,禁用默认行为,而执行其他操作。


xAxis group

xAxis.activeValue : real [read-only]

xAxis.enabled : bool

xAxis.maximum : real

xAxis.minimum : real

xAxis 控制目标项水平平移的约束条件。

minimum maximum 是可接受的最大 x 坐标。如果 为 true,则允许水平拖动。enabled

activeValue 发生变化时,会发出activeValueChanged 信号,以提供变化的增量。这样做的目的是通过多个处理程序对一个属性进行增量调整。

import QtQuick

Rectangle {
    width: 100; height: 100
    color: "lightsteelblue"; antialiasing: true

    PinchHandler {
        id: handler
        target: null
        xAxis.onActiveValueChanged: (delta) => parent.radius -= delta
        yAxis.onActiveValueChanged: (delta) => parent.border.width += delta
        rotationAxis.onActiveValueChanged: (delta) => parent.rotation += delta // add
        scaleAxis.onActiveValueChanged: (delta) => parent.scale *= delta // multiply
    }

    WheelHandler {
        acceptedModifiers: Qt.NoModifier
        property: "rotation"
    }

    WheelHandler {
        acceptedModifiers: Qt.ControlModifier
        property: "scale"
    }
}

注: 该代码段是特意设计的:PinchHandler 已经知道如何移动、缩放和旋转其父项目,但该代码以一种不那么明确的方式实现了不同的行为,以说明如何在特殊情况下使用activeValueChanged


yAxis group

yAxis.activeValue : real [read-only]

yAxis.enabled : bool

yAxis.maximum : real

yAxis.minimum : real

yAxis 控制目标项垂直平移的约束条件。

minimum maximum 是可接受的最小平移 Y 坐标。如果 为 true,则允许垂直拖动。enabled

activeValue 发生变化时,会发出activeValueChanged 信号,以提供变化的增量。这样做的目的是通过多个处理程序对一个属性进行增量调整。

import QtQuick

Rectangle {
    width: 100; height: 100
    color: "lightsteelblue"; antialiasing: true

    PinchHandler {
        id: handler
        target: null
        xAxis.onActiveValueChanged: (delta) => parent.radius -= delta
        yAxis.onActiveValueChanged: (delta) => parent.border.width += delta
        rotationAxis.onActiveValueChanged: (delta) => parent.rotation += delta // add
        scaleAxis.onActiveValueChanged: (delta) => parent.scale *= delta // multiply
    }

    WheelHandler {
        acceptedModifiers: Qt.NoModifier
        property: "rotation"
    }

    WheelHandler {
        acceptedModifiers: Qt.ControlModifier
        property: "scale"
    }
}

注: 该代码段是特意设计的:PinchHandler 已经知道如何移动、缩放和旋转其父项目,但该代码以一种不那么明确的方式实现了不同的行为,以说明如何在特殊情况下使用activeValueChanged


信号文档

canceled(eventPoint point)

如果该处理程序已经抓取了给定的point ,则当抓取被其他指针处理程序或项窃取时,将发出该信号。

注: 相应的处理程序是onCanceled


grabChanged(PointerDevice::GrabTransition transition, eventPoint point)

当抓取发生与该处理程序相关的某种变化时,就会发出该信号。

transition (动词)说明发生了什么。point (对象)是被抓取或未被抓取的点。

transition 的有效值是

常量说明
PointerDevice.GrabExclusive该处理程序承担了处理point 的主要责任。
PointerDevice.UngrabExclusive该处理程序已放弃先前的独家抓取。
PointerDevice.CancelGrabExclusive该处理程序的独占抓取已被接管或取消。
PointerDevice.GrabPassive此处理程序已获得被动抓取,以监控point
PointerDevice.UngrabPassive此处理程序已放弃先前的被动抓取。
PointerDevice.CancelGrabPassive该处理程序之前的被动抓取异常终止。

注: 相应的处理程序是onGrabChanged


rotationChanged(qreal delta)

rotationChanged 信号在activeRotation (以及persistentRotation )发生变化时发出。delta 的值给出了旋转的加法变化。例如,如果用户移动手指以改变捏合距离,从而使activeRotation 从 10 度变为 30 度,则会发出rotationChanged(20) 信号。您可以用它来逐步改变项目的旋转角度:

import QtQuick

Rectangle {
    width: 100; height: 100
    color: "lightsteelblue"

    PinchHandler {
        id: handler
        target: null
        onRotationChanged: (delta) => parent.rotation += delta // add
        onScaleChanged: (delta) => parent.scale *= delta // multiply
    }
}

注: 如果直接设置persistentRotation 属性,delta 就是0

注: 相应的处理程序是onRotationChanged


scaleChanged(qreal delta)

activeScale (以及persistentScale )发生变化时,就会发出scaleChanged 信号。delta 的值表示缩放比例的乘法变化。例如,如果用户移动手指以改变捏合距离,从而使activeScale 从 2 变为 2.5,则会发出scaleChanged(1.25) 。您可以用它来逐步改变项目的缩放比例:

import QtQuick

Rectangle {
    width: 100; height: 100
    color: "lightsteelblue"

    PinchHandler {
        id: handler
        target: null
        onRotationChanged: (delta) => parent.rotation += delta // add
        onScaleChanged: (delta) => parent.scale *= delta // multiply
    }
}

注: 如果直接设置persistentScale 属性,delta 就是1

注: 相应的处理程序是onScaleChanged


translationChanged(QVector2D delta)

activeTranslation (以及persistentTranslation )发生变化时,就会发出translationChanged 信号。delta 向量给出了翻译的变化。您可以用它来逐步改变项目的位置:

import QtQuick

Window {
    width: 320; height: 240
    visible: true
    title: handler.persistentRotation.toFixed(1) + "° " +
           handler.persistentTranslation.x.toFixed(1) + ", " +
           handler.persistentTranslation.y.toFixed(1) + " " +
           (handler.persistentScale * 100).toFixed(1) + "%"

    PinchHandler {
        id: handler
        target: null
        persistentScale: 0.25
        onTranslationChanged: (delta) => {
            image.x -= delta.x
            image.y -= delta.y
        }
    }

    Image {
        id: image
        source: "images/album-cover.jpg"
        scale: handler.persistentScale
        x: -600; y: -450
    }
}

注: 如果直接设置persistentTranslation 属性,delta 就是0, 0

注: 相应的处理程序为onTranslationChanged


© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.