每当 QWidget 添加到 QApplication 的小部件树时如何接收事件?
How to receive event whenever a QWidget is added to QApplication's widget tree?
我想检查应用范围内的东西。具体来说,我想检查添加到应用程序的每个小部件。
类似的事情可以在 JavaScript/HTML 中完成,您可以在其中添加 DOM 触发 DOM 变化的突变侦听器。
我可以在 QApplication
上收听添加的小部件吗?具体来说,捕获添加到 QApplication
对象的小部件作为子对象或添加到任何顶级小部件或 它们的 子对象、子对象等的小对象...
如果不可能,最好的解决方法是什么?
最稳定的解决方案可能是每隔一段时间遍历对象层次结构,从 QApplication
作为根开始,然后用您的谓词检查每个对象。这将是低效的,这就是为什么我要求提供有关您实际想要查询的对象的更多信息的原因。另一方面,对于一个测试框架,你可能不太关心效率。
不过,也许可以做些别的事情。您可以在任何 QObject
上安装事件过滤对象,这些对象定义了它们在从 Qt 的事件系统接收到事件时如何响应。您可以在根 QApplication
对象上安装一个事件过滤器(并递归地在创建的任何子对象上)来检查事件是否为 QChildEvent
以及 added()
returns 是否为真它。如果是这样,意味着添加了一个新的子项,那么您也可以将此事件过滤器安装到该子项上。所有其他事件将原封不动地传递下去。您可以阅读有关安装事件过滤器的更多信息 here. 本质上,过滤器是一个 QObject
子类,它定义了 eventFilter()
函数,returns 对于应该过滤的事件(停止) 否则为假。当此 returns 为真时,运行 您对新创建的对象的谓词并在其上安装相同的事件过滤器。
需要注意的一个问题是 eventFilter()
函数仅接收 QObject
s。您可以通过调用 isWidgetType()
来了解该对象是否为 QWidget
,但您所知道的仅此而已。所以只要你的 predicate 能凑合使用为这些通用基础定义的方法和数据类,那应该没问题。
根据@bnaecker 的回答,这里有一些代码:
AddChildEventFilter.h
#include <QObject>
class QEvent;
class AddChildEventFilter: public QObject {
Q_OBJECT
public:
AddChildEventFilter(QObject* parent=0);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
AddChildEventFilter.cpp
#include "AddChildEventFilter.h"
#include <QEvent>
#include <QDebug>
#include <QWidget>
#include <QChildEvent>
AddChildEventFilter::AddChildEventFilter(QObject* parent):QObject(parent) {}
bool AddChildEventFilter::eventFilter(QObject* obj, QEvent* event) {
if(QWidget* widget = dynamic_cast<QWidget*>(obj)) {
if(QChildEvent* chevent = dynamic_cast<QChildEvent*>(event)) {
if(chevent->added()) {
QObject* child = chevent->child();
qDebug()<<"Child added: "<<child->metaObject()->className()<<"to"<<widget->metaObject()->className();
child->installEventFilter(new AddChildEventFilter(child));
}
}
}
return false;
}
用法:
#include "AddChildEventFilter.h"
#include <QWidget>
#include <QApplication>
void PrintAllEvents()
{
for(QWidget* widget: QApplication::allWidgets()) {
widget->installEventFilter(new AddChildEventFilter(widget));
}
}
我想检查应用范围内的东西。具体来说,我想检查添加到应用程序的每个小部件。
类似的事情可以在 JavaScript/HTML 中完成,您可以在其中添加 DOM 触发 DOM 变化的突变侦听器。
我可以在 QApplication
上收听添加的小部件吗?具体来说,捕获添加到 QApplication
对象的小部件作为子对象或添加到任何顶级小部件或 它们的 子对象、子对象等的小对象...
如果不可能,最好的解决方法是什么?
最稳定的解决方案可能是每隔一段时间遍历对象层次结构,从 QApplication
作为根开始,然后用您的谓词检查每个对象。这将是低效的,这就是为什么我要求提供有关您实际想要查询的对象的更多信息的原因。另一方面,对于一个测试框架,你可能不太关心效率。
不过,也许可以做些别的事情。您可以在任何 QObject
上安装事件过滤对象,这些对象定义了它们在从 Qt 的事件系统接收到事件时如何响应。您可以在根 QApplication
对象上安装一个事件过滤器(并递归地在创建的任何子对象上)来检查事件是否为 QChildEvent
以及 added()
returns 是否为真它。如果是这样,意味着添加了一个新的子项,那么您也可以将此事件过滤器安装到该子项上。所有其他事件将原封不动地传递下去。您可以阅读有关安装事件过滤器的更多信息 here. 本质上,过滤器是一个 QObject
子类,它定义了 eventFilter()
函数,returns 对于应该过滤的事件(停止) 否则为假。当此 returns 为真时,运行 您对新创建的对象的谓词并在其上安装相同的事件过滤器。
需要注意的一个问题是 eventFilter()
函数仅接收 QObject
s。您可以通过调用 isWidgetType()
来了解该对象是否为 QWidget
,但您所知道的仅此而已。所以只要你的 predicate 能凑合使用为这些通用基础定义的方法和数据类,那应该没问题。
根据@bnaecker 的回答,这里有一些代码:
AddChildEventFilter.h
#include <QObject>
class QEvent;
class AddChildEventFilter: public QObject {
Q_OBJECT
public:
AddChildEventFilter(QObject* parent=0);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
AddChildEventFilter.cpp
#include "AddChildEventFilter.h"
#include <QEvent>
#include <QDebug>
#include <QWidget>
#include <QChildEvent>
AddChildEventFilter::AddChildEventFilter(QObject* parent):QObject(parent) {}
bool AddChildEventFilter::eventFilter(QObject* obj, QEvent* event) {
if(QWidget* widget = dynamic_cast<QWidget*>(obj)) {
if(QChildEvent* chevent = dynamic_cast<QChildEvent*>(event)) {
if(chevent->added()) {
QObject* child = chevent->child();
qDebug()<<"Child added: "<<child->metaObject()->className()<<"to"<<widget->metaObject()->className();
child->installEventFilter(new AddChildEventFilter(child));
}
}
}
return false;
}
用法:
#include "AddChildEventFilter.h"
#include <QWidget>
#include <QApplication>
void PrintAllEvents()
{
for(QWidget* widget: QApplication::allWidgets()) {
widget->installEventFilter(new AddChildEventFilter(widget));
}
}