0

我想检查应用程序范围内的东西。具体来说,我想检查添加到应用程序中的每个小部件。

类似的事情可以在 JavaScript/HTML 中完成,您可以在其中添加触发 DOM 更改的 DOM 突变侦听器。

我可以收听添加的小部件QApplication吗?具体来说,捕获QApplication作为子级添加到对象的小部件或添加到任何顶级小部件或其级、子级等的小部件......

如果不可能,最好的解决方法是什么?

4

2 回答 2

1

最稳定的解决方案可能是每隔一段时间遍历对象层次结构,从QApplication作为根开始,并使用谓词检查每个对象。这将是低效的,这就是为什么我要求提供有关您实际想要查询的对象的更多信息。另一方面,对于一个测试框架,你可能不太关心效率。

但是,也许可以做其他事情。您可以在 any 上安装事件过滤对象QObject,这些对象定义当它们从 Qt 的事件系统接收到事件时如何响应。您可以在根QApplication对象上安装一个事件过滤器(并递归地在创建的任何子对象上),以检查事件是否为 aQChildEvent以及是否added()为它返回 true。如果这是真的,这意味着添加了一个新的孩子,那么您也可以将此事件过滤器安装到该孩子身上。所有其他事件都将原封不动地传递下去。您可以在此处阅读有关安装事件过滤器的更多信息本质上,过滤器是一个QObject子类,它定义了eventFilter()函数,对于应该过滤(停止)的事件返回 true,否则返回 false。当这返回 true 时,在新创建的对象上运行您的谓词并在其上安装相同的事件过滤器。

需要注意的一个问题是该eventFilter()函数仅接收QObjects。您可以QWidget通过调用了解对象是否为 a isWidgetType(),但您不知道更多。因此,只要您的谓词只能使用为这些通用基类定义的方法和数据,那应该没问题。

于 2016-08-26T01:11:10.013 回答
0

根据@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));
    }
}
于 2016-08-26T01:49:33.373 回答