通过 js 库中定义的函数创建 QML 项不会设置附加属性

Creating QML Item via function defined in js library doesn't set attached properties

注意:以下测试用例中QtQuickUtils.js中的函数只是抽象出从组件创建QML对象所涉及的样板URL .

测试用例:

main.qml:

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import "QtQuickUtils.js" as QtQuickUtils

Window {
    visible: true
    width: 640
    height: 480

    GridLayout {
        anchors.fill: parent
        id: container
        columns: 1
    }

    Component.onCompleted: {
        QtQuickUtils.createObjectFromComponent("qrc:///MyItem.qml", container, {
            "Layout.fillWidth": true, "Layout.fillHeight": true
            // "width": 100, "height": 100
        });
    }
}

MyItem.qml:

import QtQuick 2.0

Rectangle {
    color: "red"
}

QtQuickUtils.js:

.import QtQml 2.0 as Qml
.pragma library

function createObjectFromComponent(componentUrl, parent, properties) {
    var component = Qt.createComponent(componentUrl);
    function finishCreation() {
        console.log("finishCreation");
        if (component.status === Qml.Component.Ready) {
            var obj = component.createObject(parent, properties);
            if (obj === null) {
                console.log("Error creating object");
                return;
            }
            console.log("success in creating obj");
        } else if (component.status === Qml.Component.Error) {
            console.log("Error loading component:", component.errorString());
            return;
        }
    }
    if (component.status === Qml.Component.Ready) {
        finishCreation();
    } else {
        component.statusChanged.connect(function() { finishCreation(); });
    }
}

这没有显示任何内容(但打印了 "finishCreation" 和 "success in creating obj")。

如果我注释掉 "Layout.fillWidth": true, "Layout.fillHeight": true 行并取消注释后一行,则会显示该项目。

此外,如果我将函数从 JS 文件移动到 main.qml,则会显示该项目。

我尝试将函数从 JS 文件移动到一个新的 qml 文件中(尝试将此 QML 文件设为单例和非单例),但这并没有解决问题。

知道我做错了什么吗,以及正确的解决方法?

JS文件不知道Layout是什么,所以无法设置

// in a JS file, shared or not
function foo(item) { console.log(item.Layout) } // undefined

如果你要:

.import QtQuick.Layouts 1.3 as L // you can't import without "as" in .JS
function foo(item) { console.log(item.L.Layout) } // and it suddenly works

所以添加一个小的不便,你可以通过简单地使用来达到目的:

"L.Layout.fillWidth": true, "L.Layout.fillHeight": true

然而,它可以在没有额外步骤的情况下使用单例,因为在那里你可以做一个 "anonymous" import QtQuick.Layouts 1.3,突然间生活又变得轻松了。正如我在评论中提到的,我真的没有理由使用 pragma library,除非您可能正在使用某些第三方 JS 库。对于其他一切,QML 单例更有用,你得到了 "shared" 部分,加上对 QML 对象的支持、带有通知的属性、信号、绑定和所有这些好东西。