QWidget添加到QApplication的小部件树时如何接收事件?

时间:2016-08-25 22:31:57

标签: qt testing qapplication

我想检查一些应用程序。具体来说,我想检查添加到应用程序中的每个小部件。

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

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

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

2 个答案:

答案 0 :(得分:1)

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

然而,可能会做其他事情。您可以在任何QObject上安装事件过滤对象,这些对象定义了当他们从Qt的事件系统接收事件时他们的响应方式。您可以在根QApplication对象上安装一个事件过滤器(并在所创建的任何子项上递归),以检查事件是否为QChildEvent,并且added()是否返回true。如果这是真的,意味着添加了新的子项,那么您也可以将此事件过滤器安装到该子项上。所有其他事件将不受影响地传递。您可以阅读有关安装事件过滤器的更多信息here.本质上,过滤器是QObject子类,它定义eventFilter()函数,对于应该过滤(停止)的事件返回true,否则返回false 。如果返回true,则在新创建的对象上运行谓词,并在其上安装相同的事件过滤器。

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

答案 1 :(得分: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));
    }
}