Qt: отслеживать положение мыши во время работы QDrag - PullRequest
0 голосов
/ 24 октября 2018

Я занимаюсь разработкой приложения 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).

Однако при перетаскивании элемента я не получаю никаких событий MouseMove ни на объекте QDrag, ни на самом quickItem, что делает невозможным отслеживание положения мыши.Так как мышь перетаскивается во время перетаскивания, в Qt должно быть какое-то событие, которое часто сообщает о положении мыши, независимо от того, где на экране находится мышь.

Мне известен метод QDrag::setPixmap, однако он не позволяет мне изменять текст всплывающей подсказки во время перетаскивания и имеет некоторые другие ограничения, которых я бы хотел избежать.

Есть ли некоторыеспособ прослушивания событий перемещения мыши во время работы QDrag без использования системных системных API для конкретной платформы?

1 Ответ

0 голосов
/ 24 октября 2018

Обновление:

Я не думаю, что есть способ сделать это без использования библиотек ОС или установки положения мыши каждые X миллисекунд.Похоже, действительно специфическая проблема, которую не рассматривает фреймворк Qt.Вам нужно написать свой собственный класс для управления этим, используя win32 для Windows, x11 для Linux и эквивалент Mac.

Если вы хотите получить положение мыши, когда ваше окно активно, и выперетаскивая что-то, проверьте это:

Немного поиска Я нашел решение для получения этого, когда ваше окно имеет фокус, используя QObject::eventFilter.

Создайте класс (например, EventListener), который наследует от QObject и переопределяет eventFilter, и метод, чтобы установить его в качестве фильтра событий окна 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 о позиции мыши.

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)

...
}
...