[英]My Qt eventFilter() doesn't stop events as it should
我的eventFilter根本上有问题,因为它允许每个事件通过,而我想停止所有事件 。 我已经阅读了很多有关QEvent
, eventFilter()
等的文档,但是显然我缺少一些重要的东西。 本质上,我试图为基于QDialog
弹出窗口类创建自己的模态功能。 我想实现自己的功能,因为内置的setModal(true)
包含很多功能,例如播放QApplication::Beep()
,这些功能我想排除。 基本上,我想丢弃所有创建我的popup的事件到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*);
};
...
// 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();
}
这就是问题,过滤器不起作用。 请注意,如果我在if(...)
内编写了一个std::cout
,我看到它确实会在事件发送到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
}
当用户与主程序交互时,可以这样创建一个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'.
其他所有工作均按预期进行。 仅事件过滤器失败。 我希望过滤器删除发送到创建弹出窗口的事件。 如鼠标单击和按键,直到关闭弹出窗口 。 当有人指出我的代码中的一个小错误时,我期望我会感到非常尴尬。
你必须忽略的是,在的widget树到达所有事件window
。 因此,您需要在整个应用程序范围内安装eventFilter
,并检查要过滤的对象是否为window
的后代。 换句话说:替换
window->installEventFilter(this);
通过
QCoreApplication::instance()->installEventFilter(this);
并通过以下方式实现事件过滤器功能:
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;
}
我尝试了一下,对其进行了测试,并且对我有用。
注意:根据我的经验,在Qt中使用事件过滤器有点混乱,因为所发生的事情并不十分透明。 期望错误会不时弹出。 如果您和您的客户因此对灰显的主窗口没有问题,则可以考虑禁用主窗口。
经过大量研究的大量反馈,反馈,建议和时间,我终于找到了我认为是最佳,最安全的解决方案。 我希望对每个人表示衷心的感谢,感谢他们对库巴·奥伯所说的“(...)并不像您想的那么简单”。
我们想从小部件中过滤掉所有某些事件, 包括其子级 。 这很困难,因为事件可能在子级默认事件过滤器中捕获并响应, 然后才被程序员实现的父级自定义过滤器捕获并过滤。 以下代码通过在所有子项创建时将过滤器安装在所有子项上来解决此问题。 本示例假定使用Qt Creator UI表单,并且基于以下博客文章: 如何为所有子项安装eventfilters 。
// 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;
};
...
WidgetClassToBeFiltered::WidgetClassToBeFiltered(QWidget *parent) :
QMainWindow(parent), // Base Class constructor
ui(new Ui::WidgetClassToBeFiltered)
{
installEventFilter(this); // install filter BEFORE setupUI.
ui->setupUi(this);
}
...
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
}
请注意 ,这是可行的,因为eventfilter会在添加的子代上自行安装! 因此,它也应该在不使用UI表单的情况下工作。
请参考以下代码以过滤特定事件:-
class MainWindow : public QMainWindow
{
public:
MainWindow();
protected:
bool eventFilter(QObject *obj, QEvent *ev);
private:
QTextEdit *textEdit;
};
MainWindow::MainWindow()
{
textEdit = new QTextEdit;
setCentralWidget(textEdit);
textEdit->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == textEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Ate key press" << keyEvent->key();
return true;
} else {
return false;
}
} else {
// pass the event on to the parent class
return QMainWindow::eventFilter(obj, event);
}
}
如果要在多个窗口小部件上设置更特定的事件过滤器,则可以参考以下代码:
class KeyPressEater : public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
qDebug("Ate key press %d", keyEvent->key());
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
KeyPressEater *keyPressEater = new KeyPressEater(this);
QPushButton *pushButton = new QPushButton(this);
pushButton->installEventFilter(keyPressEater);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.