【问题标题】:How to detect dataChanged() and resourcesChanged() from QML如何从 QML 检测 dataChanged() 和 resourcesChanged()
【发布时间】:2017-03-27 08:47:28
【问题描述】:

以下代码:

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)

dataresources 并非如此。它们被声明为:

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() 信号。为什么这种设计选择是为了特别隐藏对不可见儿童所做的更改?此外,如何从 QML 中检测到data 的变化?

【问题讨论】:

    标签: qt qml qtquick2 qt-signals qqmllistproperty


    【解决方案1】:

    你为什么需要这个?

    一种可能的解决方法是监听child events。我写了一个快速附加类型 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&lt;ChildListener&gt;("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")

    【讨论】:

    • 我为什么需要它?我一直在寻找一种方法来自动检测某些类型的子项(我创建的自定义类型最终扩展了Item),onChildrenChanged() 适用于此。然后,出于好奇,我开始考虑不可见的孩子,例如您示例中的Timer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多