Qt- quick (Qt 5.3)中新的拖放机制不像预期的那样工作



我尝试在Qt 5.3中使用新的QML类型Drag, DragEventDropArea来实现拖放。这是QML Drag类型文档中的原始示例,进行了一些小修改:

import QtQuick 2.2
Item {
    width: 800; height: 600
    DropArea {
        width: 100; height: 100; anchors.centerIn: parent
        Rectangle {
            anchors.fill: parent
            color: parent.containsDrag ? "red" : "green"
        }
        onEntered: print("entered");
        onExited: print("exited");
        onDropped: print("dropped");
    }
    Rectangle {
        x: 15; y: 15; width: 30; height: 30; color: "blue"
        Drag.active: dragArea.drag.active
        // Drag.dragType: Drag.Automatic
        Drag.onDragStarted: print("drag started");
        Drag.onDragFinished: print("drag finished");
        MouseArea {
            id: dragArea
            anchors.fill: parent
            drag.target: parent
        }
    }
}

预期行为:可以用鼠标拖动小蓝色矩形(拖动目标)。如果拖动到窗口中心较大的绿色矩形上,则该矩形将变为红色,并在离开时变回绿色。此外,及时发出dragStartedenteredexit droppeddragFinished信号,并由相应的信号处理程序打印出它们的消息。

<<p> 经验丰富的行为/strong>:

依赖于Drag.dragType(见上面的注释行):

  1. Drag.dragType未设置(默认为Drag.Internal):

    拖放按描述的方式工作,但只发出输入退出的信号。其他信号(dragStarteddragFinisheddropped)被抑制。所以没有办法对DropArea的下降做出反应。

  2. Drag.dragType设置为Drag.Automatic:

    现在发出了所有的信号,但是蓝色矩形(拖动目标)不随鼠标移动。相反,鼠标光标改变其形状以显示可能的投放目标。鼠标被释放后,蓝色矩形会跳转到鼠标的最新位置。

这两种变体都不令人满意。我怎样才能得到所有的信号,并且仍然能够在拖动目标周围拖动?不幸的是,文档中对QML中的拖放操作的描述非常不清楚,特别是关于不祥的Drag.dragType

如果您打开QQuickDrag源代码并查看Drag.Internal使用的start()Drag.Automatic使用的startDrag()之间的差异,差异非常明显。start()设置了一个事件更改监听器,然后使用它来更新附加对象的位置。startDrag()不这样做。

为什么会这样?我不知道!qtquick2的拖放文档当然还有改进的空间。

有一个相当简单的解决方法:从两个世界中取其精华。使用Drag.Automatic,但不设置Drag.active,而是手动调用start()drop()。它不会调用Drag.onDragStarted()Drag.onDragFinished(),但是通过侦听MouseAreadrag.active的变化,您基本上可以免费获得它们。

下面是实际的概念:

import QtQuick 2.0
Item {
    width: 800; height: 600
    DropArea {
        width: 100; height: 100; anchors.centerIn: parent
        Rectangle {
            anchors.fill: parent
            color: parent.containsDrag ? "red" : "green"
        }
        onEntered: print("entered");
        onExited: print("exited");
        onDropped: print("dropped");
    }
    Rectangle {
        x: 15; y: 15; width: 30; height: 30; color: "blue"
        // I've added this property for simplicity's sake.
        property bool dragActive: dragArea.drag.active
        // This can be used to get event info for drag starts and 
        // stops instead of onDragStarted/onDragFinished, since
        // those will neer be called if we don't use Drag.active
        onDragActiveChanged: {
            if (dragActive) {
                print("drag started")
                Drag.start();
            } else {
                print("drag finished")
                Drag.drop();
            }
        }
        Drag.dragType: Drag.Automatic
        // These are now handled above.
        //Drag.onDragStarted: print("drag started");
        //Drag.onDragFinished: print("drag finished");
        MouseArea {
            id: dragArea
            anchors.fill: parent
            drag.target: parent
        }
    }
}

我知道这不是一个完全令人满意的解决方案,但它确实符合你期望的行为。

这个解决方案提供:

  • 所有所需事件的通知:拖拽开始,拖拽完成,进入拖拽区域,退出拖拽区域,以及拖拽区域。
  • 拖动动画由QtQuick自动处理。当使用Drag.Automatic运行样例代码时,方块不会原地冻结。

不提供:

  • 解释为什么QtQuick的拖放功能以这种方式工作,或者它是否甚至是开发者的预期行为。当前的文档似乎模棱两可。

刚刚遇到这个我自己(使用Qt 5.2,但同样的问题存在那里)。我在x轴上有一个"滑动框",我只是想知道拖动何时完成……而不是对每一个位置的变化都做出反应。我的解决方法涉及破解状态/转换,使用ScriptAction来提供逻辑。这是模拟对"onDragFinished"信号响应的简化版本。因此,虽然它没有涵盖所有的拖放信号,但它可能会为您指出正确的方向。

Rectangle {
    id: sliderControl
    height: coordinates.height
    width: 80
    color: "#F78181"
    border.color: "#FE2E2E"
    border.width: 1
    opacity: 0.4
    MouseArea {
        id: mouseArea
        anchors.fill: parent
        drag.target: sliderControl
        drag.axis: Drag.XAxis
        drag.minimumX: 0
        drag.maximumX: view.width - sliderControl.width
        hoverEnabled: true
    }
    states: [
        State {
            name: "dragging"
            when: mouseArea.drag.active
        },
        State {
            name: "finished_dragging"
            when: !mouseArea.drag.active
        }
    ]
    transitions: [
        Transition {
            from: "dragging"
            to: "finished_dragging"
            ScriptAction {
                script: console.log("finished dragging script");
            }
        }
    ]
}

ps -我知道这样的"变通方法"不符合赏金参数,但当我在这个问题上寻求帮助时,我很沮丧地只找到你的问题(没有解决方案)。希望在这条路上遇到的其他人会发现这很有用。不幸的是,我也不知道QML的Drag.dragType发生了什么。

相关内容

  • 没有找到相关文章

最新更新