本页内容

TapHandler QML Type

轻触和点击事件处理程序。更多...

Import Statement: import QtQuick
Inherits:

SinglePointHandler

属性

信号

详细说明

TapHandler 是一个用于处理触摸屏轻触或鼠标点击的处理程序。

有效点按手势的检测取决于 `gesturePolicy`。其默认值为 `DragThreshold`,这要求按压和释放操作在空间和时间上都保持紧密。 在这种情况下,TapHandler仅需使用被动抓取即可工作,因此不会干扰事件向其他Item或Input Handler的传递。因此,当您希望通过添加带有绑定和/或JavaScript回调的TapHandler来修改现有控件或Item的行为时,默认的gesturePolicy 就派上用场了。

请注意,按钮(例如QPushButton )通常在实现时并不关注按下和释放是否发生在很短的时间内:如果您按下按钮后又改变主意,则需要将手指拖动到按钮边缘之外才能取消点击。对于这种情况,请将gesturePolicy 设置为TapHandler.ReleaseWithinBounds 。

import QtQuick

Rectangle {
    id: button
    signal clicked
    property alias text: buttonLabel.text

    height: Math.max(Screen.pixelDensity * 7, buttonLabel.implicitHeight * 1.2)
    width: Math.max(Screen.pixelDensity * 11, buttonLabel.implicitWidth * 1.3)
    radius: 3
    property color dark: Qt.darker(palette.button, 1.3)
    gradient: Gradient {
        GradientStop { position: 0.0; color: tapHandler.pressed ? dark : palette.button }
        GradientStop { position: 1.0; color: dark }
    }

    TapHandler {
        id: tapHandler
        gesturePolicy: TapHandler.ReleaseWithinBounds
        onTapped: button.clicked()
    }

    Text {
        id: buttonLabel
        text: "Click Me"
        color: palette.buttonText
        anchors.centerIn: parent
    }
}

对于多点轻触手势(双击、三击等),鼠标操作时移动距离不得超过QStyleHints::mouseDoubleClickDistance(),触摸操作时不得超过QStyleHints::touchDoubleTapDistance(),且各次轻触之间的时间间隔不得超过QStyleHints::mouseDoubleClickInterval()。

另请参阅 MouseArea 和Qt Quick 示例——指针处理程序。

属性文档

acceptedButtons : flags

可触发此指针处理程序的鼠标按钮。

默认情况下,此属性设置为Qt.LeftButton 。它可以设置为鼠标按键的“或”组合,并将忽略来自其他按键的事件。

例如,可以通过两个处理程序使控件对左键和右键点击做出不同的响应:

Item {
    TapHandler {
        onTapped: console.log("left clicked")
    }
    TapHandler {
        acceptedButtons: Qt.RightButton
        onTapped: console.log("right clicked")
    }
}

注意: 在触摸屏上轻点 或在图形输入板上用触控笔轻点,会模拟点击鼠标左键的行为。可通过acceptedDevices 或acceptedPointerTypes 更改此行为。

acceptedDevices : flags

可以触发此指针处理程序的指针设备类型。

默认情况下,此属性设置为PointerDevice.AllDevices 。若将其设置为设备类型的“或”组合,则会忽略来自不匹配设备的事件。

例如,可以通过两个处理程序使控件对鼠标和触控笔的单击做出一种响应,对触摸屏的轻触做出另一种响应:

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 设置为修饰键的“或”组合,则意味着必须按下所有这些修饰键才能激活该处理程序:

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 上通过命令行参数激活)。必须按下键盘上的 Mode_switch 键。
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 。若将其设置为设备类型的“或”组合,则会忽略来自不匹配的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]

当该输入处理程序通过成功独占获取一个或多个事件点(eventPoints )而承担起处理这些事件点的全部责任时,将执行true 。这意味着它会根据这些事件点的移动情况实时更新其属性,并主动操作其target (如有)。

cursorShape : Qt::CursorShape

当鼠标悬停在parent 项上时,如果active 的值为true ,则该属性将决定此时显示的光标形状。

可用的光标形状包括:

  • Qt.ArrowCursor
  • Qt.UpArrowCursor
  • Qt.CrossCursor
  • Qt.WaitCursor
  • Qt.IBeamCursor
  • Qt.SizeVerCursor
  • Qt.SizeHorCursor
  • Qt.SizeBDiagCursor
  • Qt.SizeFDiagCursor
  • Qt.SizeAllCursor
  • Qt.BlankCursor
  • Qt.SplitV光标
  • Qt.SplitHCursor
  • Qt.指向手形光标
  • Qt.禁止光标
  • Qt.What'sThis光标
  • Qt.BusyCursor
  • Qt.张开手形光标
  • Qt.紧握手形光标
  • Qt.拖拽复制光标
  • Qt.拖拽移动光标
  • Qt.DragLinkCursor

默认值未设置,这将使parent 项的cursor 显示出来。通过将该属性设置为undefined,可将其重置为初始状态。

注意:当 此属性未被设置,或已被设置为undefined时 ,若读取其值,将返回Qt.ArrowCursor 。

另请参阅 Qt::CursorShape 、QQuickItem::cursor() 和HoverHandler::cursorShape 。

dragThreshold : int

用户必须将eventPoint 拖动多少像素,该操作才会被视为拖动手势。

默认值取决于平台和屏幕分辨率。将其设置为 undefined 可将其重置为默认值。不同处理程序在拖动手势开始时的行为各不相同。

enabled : bool

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

如果PointerHandler 的parent 属性设置为disabled ,则该处理程序实际上也将被禁用,即使enabled 属性仍保持为true 。

注意: HoverHandler 的行为有所不同:有关更多信息,请参阅其enabled 属性的文档。

exclusiveSignals : enumeration [since 6.5]

确定singleTapped()和doubleTapped()信号的排他性。

常量描述
NotExclusive(默认)当用户分别单击或双击时,会立即触发singleTapped() 和doubleTapped()。
SingleTapsingleTapped当用户点击一次时,() 会立即发出,而doubleTapped() 则永远不会发出。
DoubleTapdoubleTapped当用户点击两次时,() 会立即发出,而singleTapped() 则永远不会发出。
(SingleTap | DoubleTap)这两个信号都会被延迟,直到触发QStyleHints::mouseDoubleClickInterval() 时,这样singleTapped() 或doubleTapped() 中的任意一个都会被触发,但不会同时触发。但如果在mouseDoubleClickInterval 内发生 3 次或更多次点击,则这两个信号都不会被触发。

注意: 其余信号(如tapped() 和tapCountChanged())无论此属性如何,都会立即发出。

该属性在 Qt 6.5 中引入。

gesturePolicy : enumeration

要识别轻触或长按手势,除了必须在longPressThreshold 超时前松开手势这一约束外,还需满足空间约束。如果这些约束未得到满足,则不会发出tapped 信号,也不会递增tapCount 。如果违反了空间约束,无论按压持续了多长时间,pressed 都会立即从true变为false。

gesturePolicy 还会影响抓取行为,具体如下所述。

常量描述
TapHandler.DragThreshold

两个重叠的“点击我”按钮均可响应一次点击

按下时抓取:被动

(默认值)eventPoint 不得发生明显移动。如果鼠标、手指或触控笔的移动超出了系统范围的拖动阈值(QStyleHints::startDragDistance ),则轻点手势将被取消,即使设备或手指仍处于按下状态也是如此。 当TapHandler 需要与其他输入处理程序(例如DragHandler )或事件处理项(例如 Qt Quick Controls),因为在此情况下,TapHandler 不会进行独占捕获,而仅执行passive grab 操作。也就是说,DragThreshold 特别适合用于增强现有行为:即使另一个项或处理程序已经在响应(甚至可能位于 UI 的不同层级),它仍能对轻触/点击/长按做出反应。 以下代码片段展示了一个组件中使用的TapHandler ;但如果将该组件的两个实例堆叠在一起,当用户在两个实例上同时按下时,你会发现两个实例中的处理程序都会同时响应,因为被动捕获并不会阻止事件传播:
Item {
    width: 120; height: 80

    component Button : Rectangle {
        TapHandler {
            id: tapHandler
            gesturePolicy: TapHandler.DragThreshold // the default
            onTapped: tapFlash.start()
        }
    }

    Button { x: 10; y: 10 }
    Button { x: 30; y: 30 }
}
TapHandler.WithinBounds

当鼠标移出“点击我”按钮时,取消点击操作

按下时抓取:排他性

如果“eventPoint ”超出“parent ”项的边界,则点击手势将被取消。“TapHandler ”会在按下时捕获“exclusive grab ”,但一旦边界约束不再满足,便会立即释放该捕获。
TapHandler {
    id: tapHandler
    gesturePolicy: TapHandler.WithinBounds
    onTapped: tapFlash.start()
}
TapHandler.ReleaseWithinBounds

将“点击我”按钮拖出区域,再拖回区域内,然后松开鼠标

按下时抓取:排他性

在释放时刻(鼠标按钮被释放或手指抬起时),如果eventPoint 位于parent 项的边界之外,则不会识别点击手势。这符合按钮控件的典型行为:您可以通过将光标拖出按钮范围来取消点击,也可以在释放前将光标拖回按钮内部以改变主意。 请注意,为了检测此手势,TapHandler 必须在按下时获取exclusive grab ,并将其保留至释放为止。
TapHandler {
    id: tapHandler
    gesturePolicy: TapHandler.ReleaseWithinBounds
    onTapped: tapFlash.start()
}
TapHandler.DragWithinBounds

长按显示包含顶部、中部、底部选项的上下文菜单

按下时抓取:排他性

按下时,TapHandler 会获取exclusive grab ;此后,eventPoint 可在parent 项的边界内被拖动,同时timeHeld 属性会继续计数,且无论拖动距离多远,都会触发longPressed()信号。然而,与WithinBounds 类似,如果点超出边界,则tap手势会触发canceled(),active()变为false ,且timeHeld 停止计数。 这适用于实现“按压-拖动-释放”类型的组件(例如菜单):通过单个TapHandler 检测按压,timeHeld 驱动“展开”动画,随后用户可将光标拖动至菜单项并释放,且整个过程始终不离开包含该菜单的父场景边界。该参数于 Qt 6.3 中新增。
TapHandler {
    id: menuPopupHandler
    gesturePolicy: TapHandler.DragWithinBounds
    onPressedChanged:
        if (pressed) {
            menu.x = point.position.x - menu.width / 2
            menu.y = point.position.y - menu.height / 2
        } else {
            feedback.text = menu.highlightedMenuItem
            selectFlash.start()
        }
    onCanceled: feedback.text = "canceled"
}

《Qt Quick 示例——指针处理程序》演示了这些功能的一些用例。

注意:如果您 发现TapHandler 在某些情况下会产生与其他行为冲突的反应,首先应考虑哪种gesturePolicy 更合适。如果无法通过修改gesturePolicy 来解决问题,某些情况下最好通过调整grabPermissions 来处理,既可以在该处理程序中进行,也可以在另一个应阻止 TapHandler 反应的处理程序中进行。

grabPermissions : flags

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

常量描述
PointerHandler.TakeOverForbidden该处理程序既不会从任何类型的 Item 或 Handler 处获取抓取权限,也不会向其授予抓取权限。
PointerHandler.CanTakeOverFromHandlersOfSameType该处理程序可以从同一类的另一个处理程序那里接管独占抓取。
PointerHandler.CanTakeOverFromHandlersOfDifferentType该处理程序可以从任何类型的处理程序手中接管独占抓取。
PointerHandler.CanTakeOverFromItems此处理程序可以从任何类型的“项”中获取独占抓取权限。
PointerHandler.CanTakeOverFromAnything此处理程序可以从任何类型的“项目”或“处理程序”处获取排他性抓取权限。
PointerHandler.ApprovesTakeOverByHandlersOfSameType此处理程序允许同一类的另一个处理程序获取抓取权限。
PointerHandler.ApprovesTakeOverByHandlersOfDifferentType此处理程序允许任何类型的处理程序获取抓取。
PointerHandler.ApprovesTakeOverByItems此处理程序允许任何类型的项目获取抓取。
PointerHandler.ApprovesCancellation该处理程序允许将其抓取对象设置为 null。
PointerHandler.ApprovesTakeOverByAnything此处理程序允许任何类型的“项目”或“处理程序”接管抓取操作。

默认值为 `PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything `,这允许大多数接管场景,但可避免例如两个 `PinchHandler` 争夺同一触点的情况。

longPressThreshold : real

当eventPoint 被按下时,若要触发长按手势并发出longPressed()信号,则需按住的时间(以秒为单位);该值必须大于0 。如果在此时间限制内松开手指,且满足gesturePolicy 约束条件,则可检测到轻触。 如果longPressThreshold 的值为0 ,则计时器将被禁用,且不会发出该信号。如果longPressThreshold 被设置为undefined ,则将使用默认值,并且可以通过此属性读取该值。

默认值为将QStyleHints::mousePressAndHoldInterval()转换为秒数。

margin : real

这是超出parent 控件边界范围的余量,eventPoint 可以在该范围内触发此处理程序。例如,在PinchHandler 中,当target 同时也是parent 时,将此值设置为至少相当于普通用户手指宽度一半的距离会很有用,这样即使parent 被缩放至非常小的尺寸,仍可执行捏合手势。 或者,如果将基于TapHandler 的按钮放置在屏幕边缘附近,则可以利用这一点来符合菲茨定律(Fitts’ Law):即使该按钮在视觉上距离屏幕边缘有几像素的间距,也能对屏幕边缘的鼠标点击做出响应。

默认值为 0。

带有周围边距区域的矩形,用于扩展触控检测

parent : Item

Item ,即处理程序的作用域;Item 即其被声明的对象。处理程序将代表该 Item 处理事件,这意味着如果指针事件的至少一个eventPoints 发生在该 Item 的内部,则该事件与该 Item 相关。初始时,target() 的值与 Item 相同,但可以被重新赋值。

另请参阅 target 和QObject::parent()。

point : handlerPoint [read-only]

当前正在处理的eventPoint 。当没有点正在被处理时,该对象将重置为默认值(所有坐标均为0)。

pressed : bool [read-only]

只要鼠标或触点被按下,且按下后的任何移动都符合当前的gesturePolicy ,该属性即为true。当eventPoint 被释放或违反该策略时,pressed将变为false。

tapCount : int [read-only]

在时间和空间限制范围内发生的点击次数,该次数被视为一个手势。如果按钮状态发生变化,计数器将重置为 1。例如,要检测三连击,可以这样编写:

Rectangle {
    width: 100; height: 30
    signal tripleTap
    TapHandler {
        acceptedButtons: Qt.AllButtons
        onTapped: if (tapCount == 3) tripleTap()
    }
}

target : Item

该处理程序将操作的项。

默认情况下,它与parent 相同,即声明该处理程序的那个Item。不过,有时将目标设置为另一个Item会很有用,这样既可以在一个Item中处理事件,却操作另一个Item;或者设置为null ,以禁用默认行为并执行其他操作。

timeHeld : real [read-only]

按下的点被按住的时间(以秒为单位),且未超出拖动阈值。该值至少会在每个渲染帧中更新一次,这使得可以渲染一个动画,以显示长按将触发的操作的进度。此外,还可以根据按住的时间长短,触发一系列操作中的某一项。

小于零的值表示该处理程序的Item 内没有被按住的点。

注意:如果 gesturePolicy 设置为TapHandler.DragWithinBounds ,即使按压点移动到了拖动阈值之外,timeHeld 也不会停止计数,只有当该点离开parent 项的bounds 时才会停止。

信号文档

canceled(eventPoint point)

如果该处理器已经获取了给定的point ,当该获取被另一个指针处理器或项目抢占时,将发出此信号。

注意: 对应的处理程序 是onCanceled 。

doubleTapped(eventPoint eventPoint, Qt::MouseButton button)

当在较短的时间间隔(QStyleHints::mouseDoubleClickInterval())和距离(QStyleHints::mouseDoubleClickDistance() 或QStyleHints::touchDoubleTapDistance())内双击“parent ”控件时,将触发此信号。该信号总是在singleTapped 、tapped 和tapCountChanged 之后发生。eventPoint 信号参数包含来自释放事件的关于被点击点的信息,而button 表示被点击的mouse button ,或在触摸屏上的NoButton 。

注意: 相应的处理程序 是onDoubleTapped 。

grabChanged(PointerDevice::GrabTransition transition, eventPoint point)

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

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

transition 的有效值包括:

常量描述
PointerDevice.GrabExclusive该处理程序已承担处理point 的主要责任。
PointerDevice.UngrabExclusive该处理程序已放弃其先前的独占抓取。
PointerDevice.CancelGrabExclusive该处理程序的独占控制已被接管或取消。
PointerDevice.GrabPassive该处理程序已获得被动监听权限,用于监视point 。
PointerDevice.UngrabPassive该处理程序已放弃其先前的被动抓取。
PointerDevice.CancelGrabPassive该处理程序之前的被动抓取已异常终止。

注: 相应的处理程序 为onGrabChanged 。

longPressed()

当parent 项被按住的时间超过longPressThreshold 时,将发出此信号。也就是说,如果你按住一个触点或按钮,且任何移动都不超过拖动阈值,那么当timeHeld 超过longPressThreshold 时,将发出longPressed 信号。

注意: 相应的处理程序 为onLongPressed 。

singleTapped(eventPoint eventPoint, Qt::MouseButton button)

当点击“parent ”项一次时,会触发此信号。经过一段大于QStyleHints::mouseDoubleClickInterval 的时间后,可以再次点击;但如果距离下次点击的时间少于该值,则tapCount 将增加。eventPoint 信号参数包含来自释放事件的关于被点击点的信息,而button 是被点击的mouse button ,或在触摸屏上为NoButton 。

注意: 对应的处理程序 是onSingleTapped 。

tapCountChanged()

当“parent ”项目被点击一次或多次(在指定的时间和距离范围内),且当前的“tapCount ”与上次的“tapCount ”不同时,会发出此信号。

注意: 相应的处理程序 为onTapCountChanged 。

tapped(eventPoint eventPoint, Qt::MouseButton button)

每次点击parent 控件时,都会触发此信号。

也就是说,如果在小于longPressThreshold 的时间内按下并释放一个触点或按钮,且任何移动均未超过拖动阈值,则在释放时将触发tapped 信号。eventPoint 信号参数包含来自释放事件的关于被点击点的信息,而button 表示被点击的mouse button ,或在触摸屏上为NoButton 。

import QtQuick

Rectangle {
    width: 100
    height: 100

    TapHandler {
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        onTapped: (eventPoint, button)=> console.log("tapped", eventPoint.device.name,
                                             "button", button,
                                             "@", eventPoint.scenePosition)
    }
}

注意: 对应的处理程序 为onTapped 。

© 2026 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.