【问题标题】:Querying global mouse position in QML在 QML 中查询全局鼠标位置
【发布时间】:2017-11-23 08:56:00
【问题描述】:

我正在用 QML 编写一个小型 PoC。在我的代码中的几个地方,我需要绑定/查询全局鼠标位置(例如,场景或游戏窗口中的鼠标位置)。即使鼠标位于我迄今为止定义的 MouseAreas 之外。

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

我在这里遗漏了什么吗?这似乎是一个很常见的情况 - 有没有更简单/更优雅的方法来实现它?

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

MouseEventSpy 取自 here 以响应其中一个答案。它仅被修改为将位置作为参数包含在信号中。

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
            }
        }
    }
}

【问题讨论】:

  • 能否也提供MouseEventSpy的修改代码?
  • 几乎没有修改,我将信号原型改为:void mouseEventDetected(int x, int y);,然后:... && event->spontaneous()) { QMouseEvent * me = (QMouseEvent*) event; emit mouseEventDetected(me->globalX(), me->globalY()); }
  • 好像和Drag.dragType有关。如果注释掉,它似乎工作。我看看能不能找到解决办法。
  • 查看我的编辑以获取修复。您需要处理 QDragMoveEvents 的情况。
  • 我将链接添加到MouseEventSpy,否则您的示例将不完整。

标签: qml qtquick2 qt-quick


【解决方案1】:

您可以在 QGuiApplication 上安装eventFilter,所有鼠标事件都将通过。

描述了如何做到这一点here

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

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


正如链接答案中提供的那样,MouseEventSpy 将仅处理各种类型的QMouseEvents。一旦你开始拖动某些东西,就不会出现QMouseEvents,而是QDragMoveEvents 等。因此,您需要扩展 filter 方法来处理这些。

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);
}

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

【讨论】:

  • 我已经尝试修改您的方法,但不幸的是它不适用于以下情况 - 我在屏幕上有一个 MouseArea,我按下它并开始拖动。一旦鼠标离开这个鼠标区域,鼠标移动事件就停止了,所以没有其他项目得到鼠标位置更新..
  • 你能发布那个代码吗?我没有这些问题。办公室。如果鼠标离开应用程序,它将不会收到事件。
【解决方案2】:

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

【讨论】:

  • 问题是当鼠标位于当前存在的鼠标区域之外时,我有时需要检查鼠标位置。在这种情况下(似乎)我没有得到任何允许我更新当前鼠标位置的鼠标移动事件。
【解决方案3】:

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

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

【讨论】:

  • 这似乎非常适合查询,但无法绑定到它。我遇到的问题情况(如添加到原始帖子中)是当我拖出 MouseArea 时 - 在这种情况下,没有收到鼠标移动事件,也没有任何东西可以更新当前鼠标位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多