我正在开发具有多个窗口的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?
答案 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)
...
}