在 QML 中查询全局鼠标位置

Querying global mouse position in QML

我正在用 QML 编写一个小型 PoC。在我的代码中的几个地方,我需要绑定 to/query 全局鼠标位置(例如,场景或游戏中的鼠标位置 window)。即使鼠标位于我目前定义的 MouseAreas 之外。

环顾四周,唯一的方法似乎是用另一个 MouseArea 覆盖整个屏幕,最有可能启用悬停。然后我还需要处理半手动传播(悬停)事件到底层 mouseAreas..

我是不是漏掉了什么?这似乎是一个很常见的情况 - 是否有 simpler/more 优雅的方法来实现它?

编辑: 最有问题的情况似乎是在鼠标区域外拖动时。下面是一个简约的例子(它使用 V-Play 组件和来自 derM 的答案的鼠标事件间谍)。当我单击图像并拖动到 MouseArea 之外时,鼠标事件不再发生,因此无法更新位置,除非下面有一个 DropArea。

The MouseEventSpy is taken from in response to one of the answers. It is only modified to include the position as parameters to the signal.

import VPlay 2.0
import QtQuick 2.0
import MouseEventSpy 1.0

GameWindow {
    id: gameWindow
    activeScene: scene
    screenWidth: 960
    screenHeight: 640

    Scene {
        id: scene
        anchors.fill: parent

        Connections {
            target: MouseEventSpy
            onMouseEventDetected: {
                console.log(x)
                console.log(y)
            }
        }

        Image {
            id: tile
            x: 118
            y: 190
            width: 200
            height: 200
            source: "../assets/vplay-logo.png"
            anchors.centerIn: parent

            Drag.active: mausA.drag.active
            Drag.dragType: Drag.Automatic

            MouseArea {
                id: mausA
                anchors.fill: parent
                drag.target: parent
            }
        }
    }
}

由于您只有几个地方需要查询全局鼠标位置,我建议您使用 mapToGlobal or mapToItem 方法。

我相信你可以从 C++ 端获取光标的坐标。查看 上的答案。该问题与您的问题无关,但解决方案也有效。

在我这边,我通过直接调用 mousePosProvider.cursorPos() 而没有任何 MouseArea 来设法获得全局坐标。

你可以在QGuiApplication上安装一个eventFilter,所有的鼠标事件都会通过。

描述了如何做到这一点

在链接的解决方案中,我在发出信号时删除了有关鼠标位置的信息。但是,您可以通过将传递给 eventFilter(...) 方法的 QEvent 转换为 QMouseEvent 并将其作为参数添加到信号中来轻松检索信息。

在链接的答案中,我将其注册为 QML 和 C++ 中可用的单例,因此您可以在任何需要的地方连接到信号。


正如链接答案中提供的那样,MouseEventSpy 将仅处理各种类型的 QMouseEvents。一旦你开始拖东西,就不会有 QMouseEvents 而是 QDragMoveEvents e.t.c。因此,您需要扩展过滤器方法,以处理这些问题。

bool MouseEventSpy::eventFilter(QObject* watched, QEvent* event)
{
    QEvent::Type t = event->type();
    if (t == QEvent::MouseButtonDblClick
            || t == QEvent::MouseButtonPress
            || t == QEvent::MouseButtonRelease
            || t == QEvent::MouseMove) {
        QMouseEvent* e = static_cast<QMouseEvent*>(event);
        emit mouseEventDetected(e->x(), e->y());
    }

    if (t == QEvent::DragMove) {
        QDragMoveEvent* e = static_cast<QDragMoveEvent*>(event);
        emit mouseEventDetected(e->pos().x(), e->pos().y());
    }
    return QObject::eventFilter(watched, event);
}

然后您可以将坐标转换为您需要的任何内容(屏幕,Window,...)