C++ 如何丢弃QEvent而不是忽略它
我有两个小部件C++ 如何丢弃QEvent而不是忽略它,c++,qt,drag-and-drop,drag,qevent,C++,Qt,Drag And Drop,Drag,Qevent,我有两个小部件ParentWidget和ChildWidget都是从QWidget派生的,并且都覆盖void dragEnterEvent(QDragEnterEvent*event) 现在ChildWidget包含在ParentWidget中。现在假设调用的某个QDragEvent*事件可能对ParentWidget有效,但对ChildWidget无效,并假设调用了ChildWidget的dragEnterEvent 现在我可以调用event->ignore()来忽略ChildWidget的事
ParentWidget
和ChildWidget
都是从QWidget
派生的,并且都覆盖void dragEnterEvent(QDragEnterEvent*event)
现在ChildWidget
包含在ParentWidget
中。现在假设调用的某个QDragEvent*
事件可能对ParentWidget
有效,但对ChildWidget
无效,并假设调用了ChildWidget
的dragEnterEvent
现在我可以调用event->ignore()
来忽略ChildWidget
的事件,但是随后调用ParentWidget
的dragEnterEvent
这就是我的问题。我不希望调用ParentWidget
的dragEnterEvent
,如果该事件已在ChildWidget
中丢弃
简单地说,我只是不希望事件被忽略,而且需要在ChildWidget
的dragEnterEvent
中完全丢弃事件
假设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();
}
#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”
int main(int argc,char**args){
QApplication应用程序(argc、args);
autowidget=新的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();
}
}
};
#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();
}
}
};
#pragma once
#include <QWidget>
#include <QUrl>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QLabel>
#include <QDebug>
#include <QByteArray>
#include <QHBoxLayout>
//#include "MyDragEnterEvent.h"
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) {
qDebug() << "Child";
if (auto mimeData=event->mimeData()) {
auto url = QUrl(mimeData->text());
if (!url.isValid()) { event->setDropAction(Qt::DropAction::IgnoreAction); event->ignore(); return; }
if (!url.isLocalFile()) { event->setDropAction(Qt::DropAction::IgnoreAction); event->ignore(); return; }
auto filename = url.fileName();
if (!filename.endsWith(".txt")) { event->setDropAction(Qt::DropAction::IgnoreAction); event->ignore(); return; }
// ChildWidget can only process txt files.
qDebug() << url.fileName();
event->acceptProposedAction();
}
else {
qDebug() << "Ignored in Child";
event->setDropAction(Qt::DropAction::IgnoreAction);
event->ignore();
}
}
};
#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 {
if (event->dropAction() == Qt::IgnoreAction) {
qDebug() << "Ignored in Parent";
event->ignore();
}
else {
qDebug() << "Accepted in Parent";
event->acceptProposedAction();
}
}
};
#pragma一次
#包括
#包括
#包括
#包括
#包括
#包括“ChildWidget.h”
类ParentWidget:publicqwidget{
Q_对象
公众:
ParentWidget(QWidget*parent=nullptr):QWidget(parent){
setLayout(新的QHBoxLayout);
setAcceptDrops(真);
layout()->addWidget(新的QLabel(“父标签”);
layout()->addWidget(新的ChildWidget);
}
作废dragEnterEvent(QDragEnterEvent*事件)重写{
qDebug()位置()){
事件->忽略();
}
否则{
事件->AcceptProposeAction();
}
}
};
ChildWidget.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();
}
}
};
#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();
}
}
};
#pragma once
#include <QWidget>
#include <QUrl>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QLabel>
#include <QDebug>
#include <QByteArray>
#include <QHBoxLayout>
//#include "MyDragEnterEvent.h"
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) {
qDebug() << "Child";
if (auto mimeData=event->mimeData()) {
auto url = QUrl(mimeData->text());
if (!url.isValid()) { event->setDropAction(Qt::DropAction::IgnoreAction); event->ignore(); return; }
if (!url.isLocalFile()) { event->setDropAction(Qt::DropAction::IgnoreAction); event->ignore(); return; }
auto filename = url.fileName();
if (!filename.endsWith(".txt")) { event->setDropAction(Qt::DropAction::IgnoreAction); event->ignore(); return; }
// ChildWidget can only process txt files.
qDebug() << url.fileName();
event->acceptProposedAction();
}
else {
qDebug() << "Ignored in Child";
event->setDropAction(Qt::DropAction::IgnoreAction);
event->ignore();
}
}
};
#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 {
if (event->dropAction() == Qt::IgnoreAction) {
qDebug() << "Ignored in Parent";
event->ignore();
}
else {
qDebug() << "Accepted in Parent";
event->acceptProposedAction();
}
}
};
#pragma一次
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类ChildWidget:publicqwidget{
Q_对象
公众:
ChildWidget(QWidget*parent=nullptr):QWidget(parent){
setAcceptDrops(真);
setLayout(新的QHBoxLayout);
layout()->addWidget(新的QLabel(“ChildLabel”);
}
作废dragEnterEvent(QDragEnterEvent*事件)重写{
qDebug()mimeData()){
自动url=QUrl(mimeData->text());
如果(!url.isValid()){event->ignore();return;}
如果(!url.isLocalFile()){event->ignore();return;}
自动文件名=url.filename();
如果(!filename.endsWith(“.txt”){event->ignore();return;}
//ChildWidget只能处理txt文件。
qDebug()接受建议动作();
}
否则{
事件->忽略();
}
}
};
您的解决方案是一个不错的解决方案
或者,可以将事件类型更改为非拖动事件。由于事件不再是QDragEnterEvent
,因此它不会被分派到父级。有两种实现方法:一种是更改QEvent
的t
(type)成员。另一种方法是就地销毁事件并在那里重新创建一个纯空事件
// https://github.com/KubaO/stackoverflown/tree/master/questions/event-discard-43885834
#include <QtWidgets>
void wipeEvent(QEvent * event) {
struct Helper : QEvent {
static void wipe(QEvent * e) {
static_cast<Helper*>(e)->t = QEvent::None;
}
};
Helper::wipe(event);
}
void wipeEvent2(QEvent *event) {
event->~QEvent(); // OK since the destructor is virtual.
new (event) QEvent(QEvent::None);
}
class ChildWidget : public QWidget {
Q_OBJECT
QHBoxLayout m_layout{this};
QLabel m_label{"ChildLabel"};
public:
ChildWidget() {
setAcceptDrops(true);
m_layout.addWidget(&m_label);
}
void dragEnterEvent(QDragEnterEvent *event) override {
qDebug() << "Child";
while (auto mimeData=event->mimeData()) {
auto url = QUrl(mimeData->text());
if (!url.isValid()) break;
if (!url.isLocalFile()) break;
auto filename = url.fileName();
if (!filename.endsWith(".txt")) break;
// ChildWidget can only process txt files.
qDebug() << url.fileName();
return event->acceptProposedAction();
}
wipeEvent(event);
}
};
class ParentWidget : public QWidget {
Q_OBJECT
QHBoxLayout m_layout{this};
QLabel m_label{"ParentLabel"};
ChildWidget m_child;
public:
ParentWidget() {
setAcceptDrops(true);
m_layout.addWidget(&m_label);
m_layout.addWidget(&m_child);
}
void dragEnterEvent(QDragEnterEvent *event) override {
qDebug() << "Parent";
event->acceptProposedAction();
}
};
int main(int argc, char** args) {
QApplication app{argc, args};
ParentWidget widget;
widget.show();
app.exec();
}
#include "main.moc"
//https://github.com/KubaO/stackoverflown/tree/master/questions/event-discard-43885834
#包括
无效事件(QEvent*事件){
结构帮助程序:QEvent{
静态空隙擦拭(QEvent*e){
静态(e)->t=QEvent::无;
}
};
Helper::擦除(事件);
}
无效事件2(QEvent*事件){
event->~QEvent();//由于析构函数是虚拟的,所以确定。
新(事件)QEvent(QEvent::None);
}
类ChildWidget:publicqwidget{
Q_对象
QHBoxLayout m_layout{this};
QLabel m_标签{“ChildLabel”};
公众:
ChildWidget(){
setAcceptDrops(真);
m_layout.addWidget(&m_标签);
}
作废dragEnterEvent(QDragEnterEvent*事件)重写{
qDebug()mimeData()){
自动url=QUrl(mimeData->text());
如果(!url.isValid())中断;
如果(!url.isLocalFile())中断;
自动文件名=url.filename();
如果(!filename.endsWith(“.txt”))中断;
//ChildWidget只能处理txt文件。
qDebug()接受建议动作();
}
事件(事件),;
}
};
类ParentWidget:publicqwidget{
Q_对象
QHBoxLayout m_layout{this};
QLabel m_标签{“ParentLabel”};
ChildWidget mu child;
公众:
ParentWidget(){
setAcceptDrops(真);
m_layout.addWidget(&m_标签);
m_layout.addWidget(&m_child);
}
作废dragEnterEvent(QDragEnterEvent*事件)重写{
qDebug()接受建议动作();
}
};
int main(int argc,char**args){
QApplication app{argc,args};
ParentWidget小部件;
widget.show();
app.exec();
}
#包括“main.moc”
如果希望丢弃事件,则需要接受它:
void dragEnterEvent(QDragEnterEvent *event) override {
qDebug() << "Child";
if (auto mimeData=event->mimeData()) {
[...]
event->acceptProposedAction();
}
else {
event->setAction(Qt::IgnoreAction);
event->accept();
}
}
经过昨天的长谈,我找到了以下更好的方法来解决我的问题。这个解决方案与Benjamin T的类似。再次感谢ThibautB。感谢富有成果的讨论 这是我的工作代码 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();
}
#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”
int main(int argc,char**args){
质量保证