本页内容

DragHandler QML Type

拖拽处理程序。更多...

Import Statement: import QtQuick
Inherits:

MultiPointHandler

属性

信号

  • canceled(eventPoint point)
  • grabChanged(PointerDevice::GrabTransition transition, eventPoint point)

详细说明

DragHandler 是一种用于交互式移动项(Item)的处理程序。与其他输入处理程序一样,它默认即具备完整功能,并可操作其拖拽项(target )。

import QtQuick

Rectangle {
    width: 100
    height: 100
    color: "lightsteelblue"
    DragHandler { }
}

它具有用于限制拖动范围的属性。

如果它在某个 Item 内被声明,但被分配了不同的target ,那么它会在parent Item 的边界内处理事件,但实际操作的却是target Item:

import QtQuick

Item {
    width: 640
    height: 480

    Rectangle {
        id: feedback
        border.color: "red"
        width: Math.max(10, handler.centroid.ellipseDiameters.width)
        height: Math.max(10, handler.centroid.ellipseDiameters.height)
        radius: Math.max(width, height) / 2
        visible: handler.active
    }

    DragHandler {
        id: handler
        target: feedback
    }
}

第三种用法是将target 设置为null ,并通过其他方式响应属性变化:

import QtQuick

Item {
    width: 640
    height: 480

    DragHandler {
        id: handler
        target: null
    }

    Text {
        color: handler.active ? "darkgreen" : "black"
        text: handler.centroid.position.x.toFixed(1) + "," + handler.centroid.position.y.toFixed(1)
        x: handler.centroid.position.x - width / 2
        y: handler.centroid.position.y - height
    }
}

如果将 minimumPointCount 和 maximumPointCount 设置为大于 1 的值,用户需要用该数量的手指朝同一方向拖动才能开始拖动。 多指拖动手势可以独立于同一项上的(默认)单指 DragHandler 和PinchHandler 进行检测,因此可用于独立于常规捏合行为之外调整其他功能:例如调整倾斜变换,或者当target 设置为 null 时调整其他数值。 但如果target 是一个Item,则centroid 是拖动开始的点,也是target 将被移动到的点(受约束条件限制)。

DragHandler 可与Drag 附加属性配合使用,以实现拖放功能。

另请参阅 Drag 、MouseArea 以及Qt Quick 示例——指针处理程序。

属性文档

acceptedButtons : flags

可触发此DragHandler 的鼠标按钮。

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

例如,如果某个组件(如TextEdit )已经以自己的方式处理了左键拖动,则可以通过添加一个DragHandler 来对其进行扩展,当通过右键拖动时,该组件将执行不同的操作:

Rectangle {
    id: canvas
    width: 640
    height: 480
    color: "#333"
    property int highestZ: 0

    Repeater {
        model: FolderListModel { nameFilters: ["*.qml"] }

        delegate: Rectangle {
            required property string fileName
            required property url fileUrl
            required property int index

            id: frame
            x: index * 30; y: index * 30
            width: 320; height: 240
            property bool dragging: ldh.active || rdh.active
            onDraggingChanged: if (dragging) z = ++canvas.highestZ
            border { width: 2; color: dragging ? "red" : "steelblue" }
            color: "beige"
            clip: true

            TextEdit {
                // drag to select text
                id: textEdit
                textDocument.source: frame.fileUrl
                x: 3; y: 3

                BoundaryRule on y {
                    id: ybr
                    minimum: textEdit.parent.height - textEdit.height; maximum: 0
                    minimumOvershoot: 200; maximumOvershoot: 200
                    overshootFilter: BoundaryRule.Peak
                }
            }

            DragHandler {
                id: rdh
                // right-drag to position the "window"
                acceptedButtons: Qt.RightButton
            }

            WheelHandler {
                target: textEdit
                property: "y"
                onActiveChanged: if (!active) ybr.returnToBounds()
            }

            Rectangle {
                anchors.right: parent.right
                width: titleText.implicitWidth + 12
                height: titleText.implicitHeight + 6
                border { width: 2; color: parent.border.color }
                bottomLeftRadius: 6
                Text {
                    id: titleText
                    color: "saddlebrown"
                    anchors.centerIn: parent
                    text: frame.fileName
                    textFormat: Text.PlainText
                }
                DragHandler {
                    id: ldh
                    // left-drag to position the "window"
                    target: frame
                }
            }
        }
    }
}

acceptedDevices : flags

能够触发此DragHandler 的指点设备类型。

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

注意: 目前并非 所有平台都能区分鼠标和触控板;而在能够区分的平台上,您通常希望鼠标和触控板的行为保持一致。

acceptedModifiers : flags

如果设置了此属性,则必须按下指定的键盘修饰键才能对指针事件做出响应,否则将忽略这些事件。

例如,两个 DragHandler 可以执行两种不同的拖放操作,具体取决于是否按下了Control 修饰键:

GridView {
    id: root
    width: 320
    height: 480
    cellWidth: 80
    cellHeight: 80
    interactive: false

    displaced: Transition {
        NumberAnimation {
            properties: "x,y"
            easing.type: Easing.OutQuad
        }
    }

    model: DelegateModel {
        id: visualModel
        model: 24
        property var dropTarget: undefined
        property bool copy: false
        delegate: DropArea {
            id: delegateRoot

            width: 80
            height: 80

            onEntered: drag => {
                if (visualModel.copy) {
                    if (drag.source !== icon)
                        visualModel.dropTarget = icon
                } else {
                    visualModel.items.move(drag.source.DelegateModel.itemsIndex, icon.DelegateModel.itemsIndex)
                }
            }

            Rectangle {
                id: icon
                objectName: DelegateModel.itemsIndex

                property string text
                Component.onCompleted: {
                    color = Qt.rgba(0.2 + (48 - DelegateModel.itemsIndex) * Math.random() / 48,
                                    0.3 + DelegateModel.itemsIndex * Math.random() / 48,
                                    0.4 * Math.random(),
                                    1.0)
                    text = DelegateModel.itemsIndex
                }
                border.color: visualModel.dropTarget === this ? "black" : "transparent"
                border.width: 2
                radius: 3
                width: 72
                height: 72
                anchors {
                    horizontalCenter: parent.horizontalCenter
                    verticalCenter: parent.verticalCenter
                }

                states: [
                    State {
                        when: dragHandler.active || controlDragHandler.active
                        ParentChange {
                            target: icon
                            parent: root
                        }

                        AnchorChanges {
                            target: icon
                            anchors {
                                horizontalCenter: undefined
                                verticalCenter: undefined
                            }
                        }
                    }
                ]

                Text {
                    anchors.centerIn: parent
                    color: "white"
                    font.pointSize: 14
                    text: controlDragHandler.active ? "+" : icon.text
                }

                DragHandler {
                    id: dragHandler
                    acceptedModifiers: Qt.NoModifier
                    onActiveChanged: if (!active) visualModel.dropTarget = undefined
                }

                DragHandler {
                    id: controlDragHandler
                    acceptedModifiers: Qt.ControlModifier
                    onActiveChanged: {
                        visualModel.copy = active
                        if (!active) {
                            visualModel.dropTarget.text = icon.text
                            visualModel.dropTarget.color = icon.color
                            visualModel.dropTarget = undefined
                        }
                    }
                }

                Drag.active: dragHandler.active || controlDragHandler.active
                Drag.source: icon
                Drag.hotSpot.x: 36
                Drag.hotSpot.y: 36
            }
        }
    }
}

如果将此属性设置为Qt.KeyboardModifierMask (默认值),则DragHandler 会忽略修饰键。

若将acceptedModifiers 设置为修饰键的“或”组合,则表示必须同时按下所有这些修饰键才能激活该处理程序。

可用的修饰键如下:

常量描述
NoModifier不允许使用任何修饰键。
ShiftModifier必须按下键盘上的 Shift 键。
ControlModifier必须按下键盘上的 Ctrl 键。
AltModifier必须按下键盘上的 Alt 键。
MetaModifier必须按下键盘上的 Meta 键。
KeypadModifier必须按下数字小键盘上的按键。
GroupSwitchModifier仅限 X11(除非在 Windows 上通过命令行参数激活)。必须按下键盘上的 Mode_switch 键。
KeyboardModifierMask处理程序不关心按下了哪些修饰键。

另请参阅 Qt::KeyboardModifier 。

acceptedPointerTypes : flags

可触发此DragHandler 的指点设备类型(手指、触控笔、橡皮擦等)。

默认情况下,此属性设置为PointerDevice.AllPointerTypes 。如果您将其设置为设备类型的“或”组合,则系统将忽略来自不匹配设备devices 的事件。

active : bool [read-only]

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

activeTranslation : vector2d [read-only]

在执行拖动手势期间的值。手势开始时该值为0, 0 ,随着事件点向下和向右拖动,该值会逐渐增大。手势结束后,该值保持不变;当下一个拖动手势开始时,该值会重新设为0, 0 。

cursorShape : Qt::CursorShape

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

可用的光标形状包括:

  • Qt.ArrowCursor
  • Qt.UpArrowCursor
  • Qt.CrossCursor
  • Qt.WaitCursor
  • Qt.IBeamCursor
  • Qt.SizeVerCursor
  • Qt.水平调整光标
  • Qt.SizeBDiagCursor
  • Qt.SizeFDiagCursor
  • Qt.SizeAllCursor
  • Qt.BlankCursor
  • Qt.SplitV光标
  • Qt.SplitHCursor
  • Qt.指手光标
  • Qt.禁止光标
  • Qt.什么是这个光标
  • 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 属性的文档。

grabPermissions : flags

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

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

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

margin : real

parent 项边界之外的区域,eventPoint 可以在该区域内触发此处理程序。例如,您可以通过允许用户从附近的位置开始拖动,从而更轻松地拖动小型项目:

Rectangle {
    width: 24
    height: 24
    border.color: "steelblue"
    Text {
        text: "it's\ntiny"
        font.pixelSize: 7
        rotation: -45
        anchors.centerIn: parent
    }

    DragHandler {
        margin: 12
    }
}

parent : Item

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

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

persistentTranslation : vector2d

如果target 不是null ,则应用此翻译。否则,可以使用绑定对该值进行任意操作。在执行拖动手势期间,activeTranslation 会持续被添加到该值中;手势结束后,该值保持不变。

snapMode : enumeration

此属性用于设置对齐模式。

该属性用于设置对齐模式,用于将“target ”项的中心对齐到“eventPoint ”。

可能的值:

常量描述
DragHandler.NoSnap从不对齐
DragHandler.SnapAuto若在target 项外部按下eventPoint ,且 target 是parent 项的子项,则target 会进行对齐(默认)
DragHandler.SnapWhenPressedOutsideTarget如果eventPoint 被按压在 项目之外,且 是 项目的子项(默认),则target 会进行吸附target
DragHandler.SnapAlways“始终对齐”

target : Item

该处理程序将操作的 Item。

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

xAxis group

xAxis.activeValue : real [read-only]

xAxis.enabled : bool

xAxis.maximum : real

xAxis.minimum : real

xAxis 控制水平拖拽的约束条件。

minimum 是应用于target 的x 的最小有效值。maximum 是应用于target 的x 的最大有效值。如果enabled 为真,则允许水平拖拽。activeValue 与activeTranslation.x 相同。

当activeValue 发生变化时,会发出activeValueChanged 信号,以提供其变化量。此信号旨在通过多个处理程序对某个属性进行增量调整。

yAxis group

yAxis.activeValue : real [read-only]

yAxis.enabled : bool

yAxis.maximum : real

yAxis.minimum : real

yAxis 控制垂直拖拽的约束条件。

minimum 是应用于target 的y 的最小可接受值。maximum 是应用于target 的y 的最大可接受值。如果enabled 为true,则允许垂直拖动。activeValue 与activeTranslation.y 相同。

当activeValue 发生变化时,会发出activeValueChanged 信号,以提供其变化的增量。此信号旨在通过多个处理程序对某个属性进行增量调整:

import QtQuick

Rectangle {
    width: 50; height: 200

    Rectangle {
        id: knob
        width: parent.width; height: width; radius: width / 2
        anchors.centerIn: parent
        color: "lightsteelblue"

        Rectangle {
            antialiasing: true
            width: 4; height: 20
            x: parent.width / 2 - 2
        }

        WheelHandler {
            property: "rotation"
        }
    }

    DragHandler {
        target: null
        dragThreshold: 0
        yAxis.onActiveValueChanged: (delta)=> { knob.rotation -= delta }
    }
}

信号文档

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 。

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