Обнаружение перетаскивания поверх всех дочерних QWidgets - PullRequest
0 голосов
/ 04 апреля 2020

Я пытаюсь реализовать поведение перетаскивания во всем приложении. Я хотел бы выполнить какое-либо действие при удалении, независимо от того, где находится MainWindow. Проблема, с которой я сталкиваюсь, заключается в том, что в моем MainWindow у меня есть виджет, который содержит QGraphicsView, который опять же содержит QGraphicsScene, я могу обнаружить падение в любом месте приложения через EventFilter, кроме как в View и Scene. Можно ли добиться какого-то глобального поведения перетаскивания, которое я могу обнаружить из MainWindow? Я пытаюсь не распространять Logi c на все мои видимые виджеты.

Это логика перетаскивания c в моем 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);
...

1 Ответ

0 голосов
/ 07 апреля 2020

Похоже, я столкнулся с двумя проблемами здесь. Первый объясняется в этом вопросе здесь Прием капель на 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 к дочернему виджету, но, похоже, мне пришлось применить его в 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://");
}

И в конструкторе моего главного окна:

setAcceptDrops(true);
qApp->installEventFilter(mDragAndDropHandler);
connect(mDragAndDropHandler, &DragAndDropHandler::imageDropped, this, &MainWindow::loadImageFromFile);
...