如何定义“模板”,在QML孩子占位符?(How to define a “template” wit

2019-07-31 16:33发布

我真的很喜欢QML。 我想我该怎么定义组件(相当于班)和它们的属性,并从其他地方来实例化它们(相当于对象)。

我可以定义,比方说,一个按钮,有一些外观和感觉,并在其上的标签文本。 这可以实现,例如,使用该组件定义( Button.qml ):

Item {
    id: button
    property string label

    anchors.fill: parent

    Rectangle {
        anchors.fill: parent
        radius: 10
        color: "gray"

        Text {
            anchors.centerIn: parent
            font.pixelSize: 20
            text: button.label
            color: "white"
        }
    }
}

和实例化在这个主文件( main.qml ):

Rectangle {
    width: 300
    height: 200

    Button {
        anchors.centerIn: parent
        anchors.margins: 50
        label: "Hello button!"
    }
}

但我看到下列限制:我只能定义按钮模板的一些特性 ,而不是一些占位 。 在实例中定义的所有儿童都将是直接的孩子,每默认,至少,我想改变这种行为。

比方说,我希望把一个项目(假设的形象,但我并不想告诉的定义Button ,这将是一个图像)的按钮。 我想是这样的:

Item {
    id: button
    property Item contents   <-- the client can set the placeholder content here

    anchors.fill: parent

    Rectangle {
        anchors.fill: parent
        radius: 10
        color: "gray"

        Item {
            id: placeholder     <-- where the placeholder should be inserted
        }
    }

    Component.onCompleted: {
        // move the contents into the placeholder...
    }
}

我怎样才能做到这一点? 我不知道,如果使用Component.onCompleted是正确的方法。 需要注意的是,但是,在我的情况下,内容永远不会改变之后(至少在我目前的应用程序的设计...)。

另外,我想锚定到占位符内工作。 例如,如果我定义的内容是文本元件,被在其父中心(其将第一是模板本身)。 然后我的代码移动这个文本实例到占位符,然后家长锚应该是那些占位符项目,而不是模板项目。

Answer 1:

我发现了一个更漂亮的回答这个问题,在Qt的开发者日2011的演示文稿建议“Qt Quick的最佳实践和设计模式” 。

他们使用default property alias ... 别名中的子项的任何项目的任何属性。 如果你不想别名孩子 ,但给别名属性的名称,只是删除default 。 (文字孩子们每QML定义默认属性的值。)

Item {
    id: button
    default property alias contents: placeholder.children

    anchors.fill: parent

    Rectangle {
        anchors.fill: parent
        radius: 10
        color: "gray"

        Item {
            id: placeholder     <-- where the placeholder should be inserted
        }
    }
}


Answer 2:

死灵应答的情况下,其他人会在这里结束我一样。

在QT5某处沿线的默认属性变成了“ 数据 ”,而不是“孩子”。 这使得有可能增加其它类型的对象不是“项目”。 例如,连接可以添加和(回答上面我自己的问题)

所以在QT5你应该做的:

Item {
    id: button
    default property alias contents: placeholder.data

    anchors.fill: parent

    Rectangle {
        anchors.fill: parent
        radius: 10
        color: "gray"

        Item {
            id: placeholder     <-- where the placeholder should be inserted
        }
    }
}

注意: placeholder.data代替placeholder.children同时请注意,您不必使用别名contents -这可以是任何你喜欢的。 一个例子:

Item {
    id: button
    default property alias foo: placeholder.data
    ...

}


Answer 3:

其实,从我所听到的正确答案是使用QML装载机来完成你想要的东西。

[话虽如此; 我还没有真正尝试过,但它是我近期到试名单上,显得颇为直截了当]

此外,搜索其他计算器“QML加载程序”的问题,因为有许多,这将帮助您开始。



Answer 4:

您可以将项目(S)(如果你想支持占位符中的多个项目),使用这段代码:

property list<Item> contents

Component.onCompleted: {
    var contentItems = [];
    for(var i = 0; i < contents.length; ++i)
        contentItems.push(contents[i]);
    placeholder.children = contentItems;
}

请注意,您不必为内容属性的项目的列表,如单值将被QML引擎也为列表属性接受。



Answer 5:

总之(显示的想法):

import QtQuick 1.1

Item {
    width: 200
    height: 100

    //<-- the client can set the placeholder content here
    property Item contents: Rectangle {
        anchors.fill: parent
        anchors.margins: 25
        color: "red"
    }

    Rectangle {
        id: container

        anchors.fill: parent
        radius: 10
        color: "gray"

        //<-- where the placeholder should be inserted
    }

    Component.onCompleted: {
        contents.parent = container
    }
}

稍微长一些的版本(支持内容改派):

import QtQuick 1.1

Item {
    width: 200
    height: 100

    //<-- the client can set the placeholder content here
    property Item contents: Rectangle {
        //anchors can be "presupplied", or set within the insertion code
        //anchors.fill: parent
        //anchors.margins: 25
        color: "red"
    }

    Rectangle {
        id: container

        anchors.fill: parent
        radius: 10
        color: "gray"

        //<-- where the placeholder should be inserted
        //Item {
        //    id: placeholder
        //}
    }

    //"__" means private by QML convention
    function __insertContents() {
        // move the contents into the placeholder...
        contents.parent = container
        contents.anchors.fill = container
        contents.anchors.margins = 25
    }

    onContentsChanged: {
        if (contents !== null)
            __insertContents()
    }

    Component.onCompleted: {
        __insertContents()
    }
}

希望这可以帮助 :)



文章来源: How to define a “template” with child placeholders in QML?
标签: qml qt-quick