2 つのウィジェットがParentWidget
あり、ChildWidget
どちらも から派生しQWidget
、オーバーライドしていますvoid dragEnterEvent(QDragEnterEvent *event)
。
ChildWidget
に含まれるようになりましたParentWidget
。ここで、特定のQDragEvent*
呼び出しevent
が に対して有効でParentWidget
あるChildWidget
と仮定し、dragEnterEvent
forChildWidget
が呼び出されたと仮定します。
event->ignore()
これで、イベント for を無視するために呼び出すことができますChildWidget
が、その後dragEnterEvent
forParentWidget
が呼び出されます。
そして、これは私の問題です。dragEnterEvent
イベントが で既に破棄されている場合、 forParentWidget
が呼び出されることは望ましくありませんChildWidget
。
簡単に言えば、イベントを無視したくないだけでなく、 of 内でイベントを完全に破棄する必要が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();
}
}
};