【发布时间】:2017-10-08 17:02:41
【问题描述】:
我有两个小部件ParentWidget 和ChildWidget 都派生自QWidget 并且都覆盖void dragEnterEvent(QDragEnterEvent *event)。
现在ChildWidget 包含在ParentWidget 中。现在假设某个名为event 的QDragEvent* 可能对ParentWidget 有效,但对ChildWidget 无效,并假设调用ChildWidget 的dragEnterEvent。
现在我可以只调用event->ignore() 以忽略ChildWidget 的事件,但随后会调用dragEnterEvent for ParentWidget。
这是我的问题。如果事件已经在ChildWidget 中被丢弃,我不希望ParentWidget 的dragEnterEvent 被调用。
简单地说,我只是不希望事件被忽略,而且事件需要在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();
}
}
};
【问题讨论】:
-
你能展示你的实现吗?您可以为
ChildWidget重新实现dragEnterEvent,因为它是虚拟的 -
@ThibautB.,我为两个小部件实现了
dragEnterEvent,ChildWidget和ParentWidget。只是dragEnterEvent的ParentWidget应该表现不同,如果事件在dragEnterEvent的ChildWidget中被忽略。 -
@ThibautB。
QDragEnterEvent可以传输这个布尔值吗? -
如果你使用类变量是的,我认为
-
@ThibautB.,我为我的问题找到了解决方法。如果事件位置有一个子小部件,我知道该事件之前已经在子小部件中被忽略了。因此我也可以在父小部件中忽略它。以下代码进入
ParentWidget的dragEnterEvent。if (auto childWidget = childAt(event->pos())) { event->ignore(); }
标签: c++ qt drag-and-drop drag qevent