【问题标题】:How to print a list of custom properties of a QML object?如何打印 QML 对象的自定义属性列表?
【发布时间】:2014-12-19 22:23:42
【问题描述】:

已经创建了一个 QML QtObject:

QtObject {
    property int p: 42
    property int q: 44
}

在将其存储在局部变量QObject *obj 中后,如何打印所有自定义属性名称和可能的值(即上面的示例中只有pq)?我希望它适用于任何类(不仅仅是QtObject),而不是打印已经用Q_PROPERTY 声明的属性。

澄清:我所说的“自定义”并不是指通过QObject::setProperty 添加的、未使用Q_PROPERTY 声明的属性。我的意思是通过property <type> <name>: <value> 表示法在QML 中声明的属性,这些属性未在该QML 对象的QObject 子类中使用Q_PROPERTY 声明。快速测试表明QObject::dynamicPropertyNames 中没有出现这些属性。

【问题讨论】:

  • QtObject 是 QML 中每个类的基类。那么,当您说“不仅仅是 QtObject”时,您的意思是什么?
  • 我的意思是我想获得一个列表,其中不包括我已经包含在QObject 的子类的Q_PROPERTY 声明中的所有属性。这是关于如何区分它们的。
  • 在您的问题中,QML 动态属性实际上是 QML 自定义属性。例如,参见文档页面 [Inline Link](doc.qt.io/qt-5/qtqml-syntax-objectattributes.html) QML 自定义属性不同于 QObject 动态属性。所以 QML 自定义属性的名称不包含在dynamicPropertyNames() 的返回值中,当属性值发生变化时,对象无法接收到QDynamicPropertyChangeEvent

标签: qt qml qt5


【解决方案1】:

C++ 和 QML 方法

要仅打印动态属性名称,您可以在可调用的 C++ 函数中使用 QObject 的命名非常恰当的 dynamicPropertyNames() 函数:

#include <QGuiApplication>
#include <QtQml>

class Object : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int staticProperty READ staticProperty)
public:
    Object() {
        setProperty("dynamicProperty", 1);
    }

    int staticProperty() const {
        return 0;
    }

    Q_INVOKABLE void printDynamicPropertyNames() const {
        qDebug() << dynamicPropertyNames();
    }
};

int main(int argc, char** argv)
{
    QGuiApplication app(argc, argv);

    Object object;

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("object", &object);
    engine.load("main.qml");

    return app.exec();
}

#include "main.moc"

main.qml:

import QtQuick 2.3
import QtQuick.Controls 1.2

ApplicationWindow {
    width: 400
    height: 400
    visible: true

    Component.objectName: object.printDynamicPropertyNames()
}

输出:

("dynamicProperty")

仅 QML 方法

如果你想打印一个对象的所有属性,动态与否,纯粹使用 QML,使用 JavaScript 的 for...in 语法:

for..in 语句以任意顺序迭代对象的可枚举属性。对于每个不同的属性,可以执行语句。

import QtQuick 2.2

Rectangle {
    id: rect
    width: 360
    height: 360

    Component.onCompleted: {
        for (var prop in rect) {
            print(prop += " (" + typeof(rect[prop]) + ") = " + rect[prop]);
        }
    }
}

输出:

qml: objectName (string) = 
qml: parent (object) = null
qml: data (object) = [object Object]
qml: resources (object) = [object Object]
qml: children (object) = [object Object]
qml: x (number) = 0
qml: y (number) = 0
qml: z (number) = 0
qml: width (number) = 360
qml: height (number) = 360
qml: opacity (number) = 1
qml: enabled (boolean) = true
...

【讨论】:

  • 在 QML 中声明的属性不会被 Qt 视为动态属性。另一个答案中使用 QMetaObject 的方法有效。
  • 根据我的快速测试,您接受的答案将打印出 only 静态属性。在重新阅读您的问题后,我在几天前编辑了我的答案,并在 C++ 中提供了一个额外的解决方案,它只打印出动态属性名称。
  • 我在“动态”周围加上引号表示我不是指通过setProperty 设置的动态属性,而是新的,不是通过Q_PROPERTY 在QML​​ 中使用property &lt;type&gt; &lt;name&gt;: &lt;value&gt; 设置的属性声明的。我对其进行了测试,但它们并没有作为 Qt 意义上的动态属性出现。我只是没有任何其他的名字。抱歉不清楚。
  • 还不错;这是我第二次读错你的问题。 :p
  • @Marnix: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 可能是该语法的更好替代方案。
【解决方案2】:

所有关于属性、可调用方法()和信号的信息都由 QMetaObject 存储在每个QObject 中。如果要列出对象中的所有属性:

QObject *obj = findObjectMethod();
QMetaObject *meta = obj->metaObject();
int n = meta->propertyCount();
for(int i = 0; i < n; ++i)
{
  qDebug() << "Property: " << meta->property(i)->name();
}

【讨论】:

  • 我正在尝试类似的东西,我更喜欢从 C++ 中做到这一点。但是,如何不打印已使用 Q_PROPERTY 声明的所有属性?
  • 我想这毕竟是解决我的具体问题的最佳方法。要从 QML 中获取未使用 Q_PROPERTY 定义的属性,您只需过滤掉来自 staticMetaObject 的属性。
  • @Xilexio 还有另一种方法,QMetaObject::propertyOffset(),它返回您指向的实际对象中定义的第一个属性的索引。我不确定(我现在不能尝试),但对于您的示例代码,它应该返回 p 属性的索引。让我知道它是否有效。
【解决方案3】:

在 QML 中获取对象的“你的”属性

Component.onCompleted: {
    for(var property in rect)
        if (property in rect.parent === false) {
            console.log("local property:", property, typeof(rect[property]))
        }
}

【讨论】:

    猜你喜欢
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-04
    相关资源
    最近更新 更多