Как обнаружить dataChanged() и resourcesChanged() из QML

Коды ниже:

Item{
    onDataChanged: console.log("Data changed")
}

Item{
    onResourcesChanged: console.log("Resources changed")
}

бросать Cannot assign to non-existent property "onDataChanged" а также Cannot assign to non-existent property "onResourcesChanged" соответственно.

Это не так с childrenChanged() сигнал. Причина в том, что в qtdeclarative/src/quick/items/qquickitem.h, children недвижимость объявляется с помощью:

Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQmlListProperty<QQuickItem> children READ children NOTIFY childrenChanged DESIGNABLE false)

но это не так для data или же resources, Они объявлены с:

Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQmlListProperty<QObject> data READ data DESIGNABLE false)
Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQmlListProperty<QObject> resources READ resources DESIGNABLE false)

без changed() сигнал. Почему этот дизайн, в частности, скрывает изменения, сделанные на невидимых детях? Кроме того, как можно изменить data быть обнаруженным из QML?

1 ответ

Решение

Зачем тебе это нужно?

Один из возможных обходных путей - слушать дочерние события. Я написал быстрый прикрепленный тип PoC:

ChildListener.h:

#ifndef CHILDLISTENER_H
#define CHILDLISTENER_H

#include <QObject>
#include <QtQml>

class ChildListener : public QObject {
    Q_OBJECT

public:
    ChildListener(QObject *object) : QObject(object) {
        if (object)
            object->installEventFilter(this);
    }

    static ChildListener *qmlAttachedProperties(QObject *object) {
        return new ChildListener(object);
    }

signals:
    void childAdded(QObject* child);
    void childRemoved(QObject* child);

protected:
      bool eventFilter(QObject *obj, QEvent *event) override {
          Q_UNUSED(obj)
          if (QChildEvent *childEvent = dynamic_cast<QChildEvent*>(event)) {
              if (childEvent->added())
                  emit childAdded(childEvent->child());
              if (childEvent->removed())
                  emit childRemoved(childEvent->child());
          }
          return false;
      }
};

QML_DECLARE_TYPEINFO(ChildListener, QML_HAS_ATTACHED_PROPERTIES)

#endif // CHILDLISTENER_H

Зарегистрируйте это с qmlRegisterUncreatableType<ChildListener>("fr.grecko.ChildListener", 1, 0, "ChildListener", "ChildListener can only be accessed as an attached type."); и теперь вы можете использовать его так:

import fr.grecko.ChildListener 1.0
/* ... */
Timer {
    id: foo
    objectName: "My name is foo"
}
Item {
    ChildListener.onChildAdded: print("child added : ", child)
    data: [foo];
}

Это выводит: qml: child added : QQmlTimer(0x7ffe22f538e0, "My name is foo") в консоли

Другие вопросы по тегам