Qt:在 QDrag 运行时跟踪鼠标位置

标签 qt events window qml mouse

我正在开发一个具有多个窗口的 Qt 应用程序,并希望为我的程序中的某些元素实现跨窗口拖放功能。

为此,我将事件过滤器附加到要拖动的 QML 元素,并监听 MousePress/MouseMove 事件以启动拖动过程,如下所示:

QDrag *drag = new QDrag(quickItem);
QMimeData* mimeData = new QMimeData();
mimeData->setText("Test");
drag->setHotSpot(QPoint(0, 0));
drag->setMimeData(mimeData);
drag->exec();

这工作正常,但现在我想在拖动时显示一个小工具提示(作为 QWidget),跟随鼠标光标并根据鼠标当前位于的元素显示短文本(类似于在 Windows 资源管理器中拖动文件时出现的“复制到...”或“移动到...”标签)。

但是,在拖动元素时,我在 QDrag 对象和 quickItem 本身上都没有收到任何 MouseMove 事件,这使得无法跟踪鼠标位置。由于鼠标在拖动过程中被抓取,因此无论鼠标在屏幕上的哪个位置,Qt 中都应该有一些事件频繁报告鼠标位置。

我知道 QDrag::setPixmap 方法,但是这不允许我在拖动过程中更改工具提示文本,并且有一些我想避免的其他限制。

有没有什么方法可以在 QDrag 运行时监听鼠标移动事件,而不使用特定于平台的系统 API?

最佳答案

更新:

我认为如果不使用操作系统库或每 X 毫秒获取一次鼠标位置,就没有办法做到这一点。它看起来像是 Qt 框架没有考虑到的一个非常具体的问题。您将需要编写自己的类来控制它,使用适用于 Windows 的 win32、适用于 Linux 的 x11 和等效的 Mac。

如果您想在窗口处于事件状态并且正在拖动某些东西时获取鼠标位置,请检查以下内容:

经过一番搜索,我找到了一个解决方案,可以在您的窗口使用 QObject::eventFilter 获得焦点时获取它。 .

创建一个继承自 QObject 并覆盖 eventFilter 的类(例如 EventListener)和一个将其设置为您的 qml 窗口的方法(继承自 QObject ) 事件过滤器 installEventFilter .

eventslistener.h:

#include <QEvent>
#include <QObject>
#include <QDebug>
#include <QDropEvent>

class EventsListener : public QObject
{
    Q_OBJECT

public:
    EventsListener(QObject * ptr) : QObject (ptr) {
    }

    Q_INVOKABLE void handleEventsOf(QObject *object) {
        if (object)
            object->installEventFilter(this);
    }

    bool eventFilter(QObject *object, QEvent *event) override {
        if(event->type() == QEvent::DragMove) {
            QDragMoveEvent *mouseEvent = static_cast<QDragMoveEvent*>(event);

            qDebug() << "Mouse position dragging (x, y): (" << mouseEvent->pos().x() << ", " << mouseEvent->pos().y() << ")";
            return false; //this is must return false or drop event will be handled by this method and drag&drop won't work correctly
        }

        return false;
    }
};

现在我们需要使用 qmlRegisterSingletonType 访问此类的实例(在本例中为单例)。您可能希望使用 qmlRegisterType而不是将此事件监听器注册为一种类型(而不是单例),并使用信号直接通知 qml 鼠标位置。

ma​​in.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include "eventlistener.h"

static QObject *eventsListenerInstance(QQmlEngine *qmlEngine, QJSEngine *engine)
{
    return new EventsListener(engine);
}

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    qmlRegisterSingletonType<EventsListener>("AppEventListener", 1, 0, "EventsListener", eventsListenerInstance);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

主.qml:

import ...
import AppEventListener 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    id: item
    property string display
    property alias dropEnabled: acceptDropCB.checked
    color: dropArea.containsDrag ? "#CFC" : "#EEE"

    Component.onCompleted: EventsListener.handleEventsOf(item)

...
}

关于Qt:在 QDrag 运行时跟踪鼠标位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52960719/

相关文章:

Java/Javascript 将包含小程序的浏览器窗口置于前台

wpf - 如何在共享 ResourceDictionary 中定义窗口实例的默认背景颜色?

c++ - 拖放到桌面或特定文件夹中,无需临时存储。

c++ - QListView 中的独占复选框

javascript - Node.js,为事件 'data' 分配回调函数

javascript - 如何从 forEach 方法中删除不需要的计数增量?

c++ - QComboBox 已激活(int)

c++ - 缓冲区中TCP数据是否可以重叠

javascript - Jquery Cookbook 模态按钮

jquery - 窗口未定义,文档未定义- Electron