Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何丢弃QEvent而不是忽略它_C++_Qt_Drag And Drop_Drag_Qevent - Fatal编程技术网

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){
质量保证