检测拖放到所有子QWidget上

问题描述 投票:0回答:1

我正在尝试在整个应用程序中实现拖放行为,我希望在发生拖放时执行一些操作,而在MainWindow中没有其他位置。我面临的问题是,在MainWindow中,我有一个包含QGraphicsView的小部件,该小部件又包含QGraphicsScene,我可以通过EventFilter在应用程序中的任何位置(视图和场景中的除外)检测到放置。是否可以实现某种可以从MainWindow中检测到的全局拖放行为?我试图避免将逻辑分散在所有可见的小部件中。

这是我MainWindow中的拖放逻辑,正如所说的,适用于所有不在视图/场景上发生的拖放。

void MainWindow::dropEvent(QDropEvent *event)
{
    auto pixmap = QPixmap(event->mimeData()->urls().first().toString().remove("file://"));
    if(!pixmap.isNull()) {
        load(pixmap);
    }

    event->acceptProposedAction();
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasUrls()) {
        event->acceptProposedAction();
    }
}

对于在视图/场景上的拖放,我尝试安装以下事件过滤器:

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::DragEnter) {
        qDebug("Enter");
    } else if(event->type() == QEvent::Drop) {
        qDebug("Drop");
    } else if(event->type() == QEvent::GraphicsSceneDrop)   {
        qDebug("Scene drop");
    } else if (event->type() >= 159 && event->type() <= 168) {
        qDebug("Any Scene Event");
    }
    return QObject::eventFilter(obj, event);
}

并将其应用到MainWindow ctor中,我检测到的唯一一件事是进入视图时是回车。

...
setAcceptDrops(true);
mChildWidget->installEventFilter(this);
mChildWidget->setAcceptDrops(true);
...
qt drag-and-drop qgraphicsview qgraphicsscene qevent
1个回答
0
投票

似乎我在这里面临两个问题。第一个问题在此处Accepting drops on a QGraphicsScene中得到解释。 QGraphicsScene会忽略没有在项目上发生的DragAndDrops。基本上,您可以启用拖放功能,但仅可以单独用于传送项目,这样仍会留下未被项目覆盖的区域。解决此问题的方法似乎是覆盖dragMoveEvent

void MyQGprahicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
    Q_UNUSED(event)

    // Overriding default dragMoveEvent in order to accept drops without items under them
}

[我面临的第二个问题是,我试图将eventFilter应用于Child小部件,但是看起来我不得不将其应用于qApp,此后一切似乎都可以正常工作,可能是因为qApp是顶部的QObject,如果不处理,所有事件都会降落。

#include "DragAndDropHandler.h"

bool DragAndDropHandler::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::DragEnter) {
        handleDragEnter(dynamic_cast<QDragEnterEvent *>(event));
    } else if(event->type() == QEvent::Drop) {
        handleDrop(dynamic_cast<QDropEvent *>(event));
    } else if(event->type() == QEvent::GraphicsSceneDrop) {
        handleDrop(dynamic_cast<QGraphicsSceneDragDropEvent *>(event));
    } else if (event->type() ==  QEvent::GraphicsSceneDragEnter) {
        handleDragEnter(dynamic_cast<QGraphicsSceneDragDropEvent *>(event));
    }
    return QObject::eventFilter(obj, event);
}

void DragAndDropHandler::handleDragEnter(QDragEnterEvent *event)
{
    if (event->mimeData()->hasUrls()) {
        event->acceptProposedAction();
    }
}

void DragAndDropHandler::handleDragEnter(QGraphicsSceneDragDropEvent *event)
{
    if (event->mimeData()->hasUrls()) {
        event->acceptProposedAction();
    }
}

void DragAndDropHandler::handleDrop(QDropEvent *event)
{
    auto path = getUrlFromMimeData(event->mimeData());
    event->acceptProposedAction();
    emit imageDropped(path);
}

void DragAndDropHandler::handleDrop(QGraphicsSceneDragDropEvent *event)
{
    auto path = getUrlFromMimeData(event->mimeData());
    event->acceptProposedAction();
    emit imageDropped(path);
}

QString DragAndDropHandler::getUrlFromMimeData(const QMimeData *mimeData) const
{
    return mimeData->urls().first().toString().remove("file://");
}

而且,在我的MainWindow的构造函数中:

setAcceptDrops(true);
qApp->installEventFilter(mDragAndDropHandler);
connect(mDragAndDropHandler, &DragAndDropHandler::imageDropped, this, &MainWindow::loadImageFromFile);
© www.soinside.com 2019 - 2024. All rights reserved.