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

时间:2018-10-24 03:34:18

标签: 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?

1 个答案:

答案 0 :(得分:0)

更新

我不认为没有使用OS库或每隔X毫秒获取一次鼠标位置就无法做到这一点。看起来Qt框架没有考虑到一个非常具体的问题。您将需要编写自己的类来使用Windows的win32,Linux的x11和Mac的等效程序来控制该类。

如果要在窗口处于活动状态并且要拖动某些东西时获取鼠标位置,请选中此选项:

稍作搜索,我找到了一种解决方法,当您使用QObject::eventFilter将窗口聚焦时,即可获取它。

创建一个从QObject继承并覆盖eventFilter的类(例如EventListener),并创建一个方法,将其设置为您的qml窗口(从QObject继承)qml窗口,并使用{ {3}}。

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访问此类的实例(在这种情况下为单个实例)。您可能希望使用installEventFilter代替将此事件监听器注册为类型(而不是单例),并使用信号直接通知qml鼠标位置。

main.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();
}

main.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)

...
}