mag*_*nus 7 c++ qt modal-dialog
我的eventFilter出现了根本性的错误,因为它让每一个事件都通过,而我想要阻止一切.我已经阅读了很多文档QEvent,eventFilter()等等,但显然我错过了很多东西.基本上,我正在尝试为我的弹出窗口类创建自己的模态功能QDialog.我想实现自己的,因为内置setModal(true)包含很多功能,例如播放QApplication::Beep(),我想排除.基本上,我想丢弃所有进入创建弹出窗口的QWidget(窗口)的事件.到目前为止我所拥有的是,
// popupdialog.h
#ifndef POPUPDIALOG_H
#define POPUPDIALOG_H
#include <QDialog>
#include <QString>
namespace Ui {class PopupDialog;}
class PopupDialog : public QDialog
{
Q_OBJECT
public:
explicit PopupDialog(QWidget *window=0, QString messageText="");
~PopupDialog();
private:
Ui::PopupDialog *ui;
QString messageText;
QWidget window; // the window that caused/created the popup
void mouseReleaseEvent(QMouseEvent*); // popup closes when clicked on
bool eventFilter(QObject *, QEvent*);
};
Run Code Online (Sandbox Code Playgroud)
...
// popupdialog.cpp
#include "popupdialog.h"
#include "ui_popupdialog.h"
PopupDialog::PopupDialog(QWidget *window, QString messageText) :
QDialog(NULL), // parentless
ui(new Ui::PopupDialog),
messageText(messageText),
window(window)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true); // Prevents memory leak
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
ui->message_text_display->setText(messageText);
window->installEventFilter(this);
//this->installEventFilter(window); // tried this also, just to be sure ..
}
PopupDialog::~PopupDialog()
{
window->removeEventFilter(this);
delete ui;
}
// popup closes when clicked on
void PopupDialog::mouseReleaseEvent(QMouseEvent *e)
{
close();
}
Run Code Online (Sandbox Code Playgroud)
这是问题,过滤器不起作用.请注意,如果我在std::cout
里面写了一个内容if(...),我看到它会在发送事件时触发window,它只是不会阻止它们.
bool PopupDialog::eventFilter(QObject *obj, QEvent *e)
{
if( obj == window )
return true; //should discard the signal (?)
else
return false; // I tried setting this to 'true' also without success
}
Run Code Online (Sandbox Code Playgroud)
当用户与主程序交互时,可以像这样创建PopupDialog:
PopupDialog *popup_msg = new PopupDialog(ptr_to_source_window, "some text message");
popup_msg->show();
// I understand that naming the source 'window' might be a little confusing.
// I apologise for that. The source can in fact be any 'QWidget'.
Run Code Online (Sandbox Code Playgroud)
其他一切都按预期工作.只有事件过滤器失败.我希望过滤器删除发送到创建弹出窗口的窗口的事件; 比如鼠标点击和按键,直到弹出窗口关闭.当有人在我的代码中指出一个微不足道的修复时,我期待非常尴尬.
您必须忽略到达window. 因此,您需要在eventFilter应用程序范围内安装并检查您过滤的对象是否是window. 换句话说:替换
window->installEventFilter(this);
Run Code Online (Sandbox Code Playgroud)
经过
QCoreApplication::instance()->installEventFilter(this);
Run Code Online (Sandbox Code Playgroud)
并以这种方式实现事件过滤器功能:
bool PopupDialog::eventFilter(QObject *obj, QEvent *e)
{
if ( !dynamic_cast<QInputEvent*>( event ) )
return false;
while ( obj != NULL )
{
if( obj == window )
return true;
obj = obj->parent();
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
我试过了,测试了它,它对我有用。
注意:根据我的经验,在 Qt 中使用事件过滤器有点混乱,因为它不太清楚发生了什么。预计错误会不时出现。如果您和您的客户对灰显的主窗口没有问题,您可以考虑禁用主窗口。
经过大量的回应、反馈、建议和投入时间进行广泛的研究后,我终于找到了我认为是最佳、最安全的解决方案。我谨向大家表示衷心的感谢,感谢他们对库巴·奥伯所说的“(……)问题并不像你想象的那么简单”所提供的帮助。
我们想要过滤掉小部件中的所有特定事件,包括它的子部件。这很困难,因为事件可能会在子级的默认事件过滤器中捕获并响应,然后再由程序员为其实现的父级自定义过滤器捕获和过滤。以下代码通过在创建所有子项时安装过滤器来解决此问题。此示例假设使用 Qt Creator UI 表单,并基于以下博客文章: 如何为所有子级安装事件过滤器。
// The widget class (based on QMainWindow, but could be anything) for
// which you want to install the event filter on, includings its children
class WidgetClassToBeFiltered : public QMainWindow
{
Q_OBJECT
public:
explicit WidgetClassToBeFiltered(QWidget *parent = 0);
~WidgetClassToBeFiltered();
private:
bool eventFilter(QObject*, QEvent*);
Ui::WidgetClassToBeFiltered *ui;
};
Run Code Online (Sandbox Code Playgroud)
...
WidgetClassToBeFiltered::WidgetClassToBeFiltered(QWidget *parent) :
QMainWindow(parent), // Base Class constructor
ui(new Ui::WidgetClassToBeFiltered)
{
installEventFilter(this); // install filter BEFORE setupUI.
ui->setupUi(this);
}
Run Code Online (Sandbox Code Playgroud)
...
bool WidgetClassToBeFiltered::eventFilter(QObject *obj, QEvent* e)
{
if( e->type() == QEvent::ChildAdded ) // install eventfilter on children
{
QChildEvent *ce = static_cast<QChildEvent*>(e);
ce->child()->installEventFilter(this);
}
else if( e->type() == QEvent::ChildRemoved ) // remove eventfilter from children
{
QChildEvent *ce = static_cast<QChildEvent*>(e);
ce->child()->removeEventFilter(this);
}
else if( (e->type() == QEvent::MouseButtonRelease) ) // e.g. filter out Mouse Buttons Relases
{
// do whatever ..
return true; // filter these events out
}
return QWidget::eventFilter( obj, e ); // apply default filter
}
Run Code Online (Sandbox Code Playgroud)
请注意,这是有效的,因为事件过滤器会自行安装到添加的子项上!因此,它也应该在不使用 UI 表单的情况下工作。