我想检查应用程序范围内的东西。具体来说,我想检查添加到应用程序中的每个小部件。
类似的事情可以在 JavaScript/HTML 中完成,您可以在其中添加触发 DOM 更改的 DOM 突变侦听器。
我可以收听添加的小部件QApplication
吗?具体来说,捕获QApplication
作为子级添加到对象的小部件或添加到任何顶级小部件或其子级、子级等的小部件......
如果不可能,最好的解决方法是什么?
我想检查应用程序范围内的东西。具体来说,我想检查添加到应用程序中的每个小部件。
类似的事情可以在 JavaScript/HTML 中完成,您可以在其中添加触发 DOM 更改的 DOM 突变侦听器。
我可以收听添加的小部件QApplication
吗?具体来说,捕获QApplication
作为子级添加到对象的小部件或添加到任何顶级小部件或其子级、子级等的小部件......
如果不可能,最好的解决方法是什么?
最稳定的解决方案可能是每隔一段时间遍历对象层次结构,从QApplication
作为根开始,并使用谓词检查每个对象。这将是低效的,这就是为什么我要求提供有关您实际想要查询的对象的更多信息。另一方面,对于一个测试框架,你可能不太关心效率。
但是,也许可以做其他事情。您可以在 any 上安装事件过滤对象QObject
,这些对象定义当它们从 Qt 的事件系统接收到事件时如何响应。您可以在根QApplication
对象上安装一个事件过滤器(并递归地在创建的任何子对象上),以检查事件是否为 aQChildEvent
以及是否added()
为它返回 true。如果这是真的,这意味着添加了一个新的孩子,那么您也可以将此事件过滤器安装到该孩子身上。所有其他事件都将原封不动地传递下去。您可以在此处阅读有关安装事件过滤器的更多信息。本质上,过滤器是一个QObject
子类,它定义了eventFilter()
函数,对于应该过滤(停止)的事件返回 true,否则返回 false。当这返回 true 时,在新创建的对象上运行您的谓词并在其上安装相同的事件过滤器。
需要注意的一个问题是该eventFilter()
函数仅接收QObject
s。您可以QWidget
通过调用了解对象是否为 a isWidgetType()
,但您不知道更多。因此,只要您的谓词只能使用为这些通用基类定义的方法和数据,那应该没问题。
根据@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));
}
}