1

2 つのウィジェットがParentWidgetあり、ChildWidgetどちらも から派生しQWidget、オーバーライドしていますvoid dragEnterEvent(QDragEnterEvent *event)

ChildWidgetに含まれるようになりましたParentWidget。ここで、特定のQDragEvent*呼び出しeventが に対して有効でParentWidgetあるChildWidgetと仮定し、dragEnterEventforChildWidgetが呼び出されたと仮定します。

event->ignore()これで、イベント for を無視するために呼び出すことができますChildWidgetが、その後dragEnterEventforParentWidgetが呼び出されます。

そして、これは私の問題です。dragEnterEventイベントが で既に破棄されている場合、 forParentWidgetが呼び出されることは望ましくありませんChildWidget

簡単に言えば、イベントを無視したくないだけでなく、 of 内でイベントを完全に破棄する必要がdragEnterEventありChildWidgetます。

ParentWidgetChildWidgetが疎結合コンポーネントであるという仮定の下で、どのようにそのような動作を実現できますか?

最小限の例

次の例は、私が達成しようとしていることを示しており、ある意味で実行可能なアプローチでもあります。より複雑なシナリオの場合、コードが過度に複雑になります。

ChildWidgetは、で終わるファイル名のドロップを受け入れますがtxtParentWidgetは、 によってすでに無視されているものを除いて、すべてのドロップを受け入れます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();
        }
    }
};
4

3 に答える 3