gpt4 book ai didi

c++ - 如何丢弃 QEvent 而不是忽略它

转载 作者:行者123 更新时间:2023-11-30 02:25:42 25 4
gpt4 key购买 nike

我有两个小部件 ParentWidgetChildWidget 都派生自 QWidget 并且都覆盖 void dragEnterEvent(QDragEnterEvent *event)

现在 ChildWidget 包含在 ParentWidget 中。现在假设某个名为 eventQDragEvent* 可能对 ParentWidget 有效,但对 ChildWidget 无效,并假设ChildWidgetdragEnterEvent 被调用。

现在我可以调用 event->ignore() 来忽略 ChildWidget 的事件,然后调用 dragEnterEventParentWidget 被调用。

这是我的问题。我不希望,如果事件已在 ChildWidget 中被丢弃,则 ParentWidgetdragEnterEvent 将被调用。

简单地说,我只是不希望事件被忽略,而且事件需要在 ChildWidgetdragEnterEvent 中被完全丢弃。

假设 ParentWidgetChildWidget 是松散耦合的组件,如何实现这样的行为?

最小示例

以下示例展示了我正在努力实现的目标,并且在某种意义上也是一种可行的方法。如果是更复杂的场景,则会导致代码过于复杂。

ChildWidget 接受以 txt 结尾的文件名丢弃,而 ParentWidget 接受所有丢弃,除了那些已经被 忽略的子控件

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();
}
}
};

最佳答案

如果您希望事件被丢弃,您需要接受它:

void dragEnterEvent(QDragEnterEvent *event) override {
qDebug() << "Child";
if (auto mimeData=event->mimeData()) {
[...]
event->acceptProposedAction();
}
else {
event->setAction(Qt::IgnoreAction);
event->accept();
}
}

这就是 Qt 向小部件分派(dispatch)事件的方式:事件从子部件传播到父部件,直到小部件接受它。

来自Qt代码:

while (w) {
if (w->isEnabled() && w->acceptDrops()) {
res = d->notify_helper(w, dragEvent); // calls dragEnterEvent() on w
if (res && dragEvent->isAccepted()) {
QDragManager::self()->setCurrentTarget(w);
break; // The event was accepted, we break, the event will not propagate to the parent
}
}
if (w->isWindow())
break;
dragEvent->p = w->mapToParent(dragEvent->p.toPoint());
w = w->parentWidget();
}

关于c++ - 如何丢弃 QEvent 而不是忽略它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43885834/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com