如何在QML中使用子占位符定义"模板"?

lee*_*mes 27 qt qml qt-quick

我真的很喜欢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"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并在此主文件(main.qml)中实例化:

Rectangle {
    width: 300
    height: 200

    Button {
        anchors.centerIn: parent
        anchors.margins: 50
        label: "Hello button!"
    }
}
Run Code Online (Sandbox Code Playgroud)

但我看到以下限制:我只能定义一个带有一些属性的按钮模板,而不是一些占位符.实例中定义的所有子项都是直接子项,至少是默认值,我想更改此行为.

假设我想在按钮中放置一个项目(让我们说一个图像,但我不想告诉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...
    }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?我不知道使用Component.onCompleted是否正确.但请注意,在我的情况下,内容永远不会改变(至少在我当前的应用程序设计中......).

此外,我希望锚定在占位符内工作.例如,如果我将内容定义为Text元素,则以其父元素为中心(首先是模板本身).然后我的代码将此Text实例移动到占位符中,然后父锚点应该是占位符项的那些,而不是模板项.

lee*_*mes 36

我在Qt开发者日2011 "Qt快速最佳实践和设计模式"的演示中提出了一个更好的答案.

他们使用default property alias ...别名中的子项的任何项目的任何属性.如果你不想别名孩子,但给别名属性的名称,只是删除default.(Literal children是每个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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 以这种方式将Connections QML对象添加到模板会给您一个错误:"无法将对象分配给列表属性"内容" - 如何处理? (3认同)

Lar*_*pon 8

Necro回答以防其他人像我一样在这里结束.

在Qt5沿线的某处,默认属性变为" 数据 "而不是"子".这使得可以添加除"Item"之外的其他对象类型.例如,也可以添加连接(以回答我上面提到的问题)

所以在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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意: placeholder.data而不是placeholder.children 请注意,您不必使用别名contents- 这可以是您喜欢的任何内容.一个例子:

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

}
Run Code Online (Sandbox Code Playgroud)