У меня есть два виджета ParentWidget
и ChildWidget
, оба производные от QWidget
и оба переопределяющие void dragEnterEvent(QDragEnterEvent *event)
.
Теперь ChildWidget
содержится в ParentWidget
. Теперь предположим, что некий QDragEvent*
, называемый event
, может быть действительным для ParentWidget
, но не для ChildWidget
, и предположим, что dragEnterEvent
вызывается для ChildWidget
.
Теперь я могу просто вызвать event->ignore()
, чтобы проигнорировать событие для ChildWidget
, но тогда вызывается dragEnterEvent
для ParentWidget
.
И это моя проблема. Я не хочу, чтобы вызывалось dragEnterEvent
для ParentWidget
, если событие уже было отброшено в ChildWidget
.
Проще говоря, я просто не хочу, чтобы событие просто игнорировалось, но, кроме того, событие должно быть полностью отброшено внутри dragEnterEvent
из ChildWidget
.
Как можно добиться такого поведения, если предположить, что ParentWidget
и ChildWidget
являются слабо связанными компонентами?
Минимальный пример
Следующий пример показывает, чего я пытаюсь достичь, а также в некотором смысле является работоспособным подходом. В случае более сложных сценариев это приведет к чрезмерно сложному коду.
ChildWidget
допускает отбрасывание имен файлов, оканчивающихся на txt
, тогда как ParentWidget
принимает все отбрасывания, кроме тех, которые уже игнорируются ChildWidget
.
main.cpp
#include <QApplication>
#include "ParentWidget.h"
int main(int argc, char** args) {
QApplication app(argc, args);
auto widget=new ParentWidget;
widget->show();
app.exec();
}
ParentWidget.h
#pragma once
#include <QWidget>
#include <QDebug>
#include <QDragEnterEvent>
#include <QHBoxLayout>
#include <QLabel>
#include "ChildWidget.h"
class ParentWidget : public QWidget {
Q_OBJECT
public:
ParentWidget(QWidget* parent = nullptr) : QWidget(parent) {
setLayout(new QHBoxLayout);
setAcceptDrops(true);
layout()->addWidget(new QLabel("ParentLabel"));
layout()->addWidget(new ChildWidget);
}
void dragEnterEvent(QDragEnterEvent *event) override {
qDebug() << "Parent";
// Check if event was already ignored in ChildWidget?
if (auto childWidget = qobject_cast<ChildWidget*>(childAt(event->pos()))) {
event->ignore();
}
else {
event->acceptProposedAction();
}
}
};
ChildWidget.h
#pragma once
#include <QWidget>
#include <QUrl>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QLabel>
#include <QDebug>
#include <QByteArray>
#include <QHBoxLayout>
class ChildWidget : public QWidget {
Q_OBJECT
public:
ChildWidget(QWidget* parent = nullptr) : QWidget(parent) {
setAcceptDrops(true);
setLayout(new QHBoxLayout);
layout()->addWidget(new QLabel("ChildLabel"));
}
void dragEnterEvent(QDragEnterEvent *event) override {
qDebug() << "Child";
if (auto mimeData=event->mimeData()) {
auto url = QUrl(mimeData->text());
if (!url.isValid()) { event->ignore(); return; }
if (!url.isLocalFile()) { event->ignore(); return; }
auto filename = url.fileName();
if (!filename.endsWith(".txt")) { event->ignore(); return; }
// ChildWidget can only process txt files.
qDebug() << url.fileName();
event->acceptProposedAction();
}
else {
event->ignore();
}
}
};
dragEnterEvent
дляChildWidget
, потому что это виртуальный - person thibsc   schedule 10.05.2017dragEnterEvent
для обоих виджетов,ChildWidget
иParentWidget
. ПростоdragEnterEvent
дляParentWidget
должно вести себя иначе, если событие было проигнорировано вdragEnterEvent
изChildWidget
. - person Aleph0   schedule 10.05.2017QDragEnterEvent
транспортировать это логическое значение? - person Aleph0   schedule 10.05.2017dragEnterEvent
файлаParentWidget
.if (auto childWidget = childAt(event->pos())) { event->ignore(); }
- person Aleph0   schedule 10.05.2017dragEnterEvent
изChildWidget
следует вызывать без вызоваdragEnterEvent
изParentWidget
- person thibsc   schedule 10.05.2017