有条件地包括基于属性值的组件

Tom*_*unn 2 qml ubuntu-touch

我有一个ListView,它显示来自API的一些数据.在我的列表项中,我需要有两个不同的组件树,具体取决于该行的数据.更具体地说,如果行具有关联的图像,我需要以特定方式显示带有标签的图像.如果它没有图像,那么我想只显示一个标签,以不同的方式排列.对我来说,这听起来像我想要创建两个不同的组件,并动态选择要包含的组件.

它目前看起来像这样,缩写形式:

ListItem.Empty {
    id: matchItem
    property string team1Name
    property string team2Name
    property string team1Logo
    property string team2Logo

    width: parent.width

    Item {
        id: team1Info
        width: parent.width*0.3

        anchors {
            left: parent.left
            top: parent.top
            bottom: parent.bottom
        }

        Item {
            anchors.fill: parent
            anchors.margins {
                top: units.gu(2)
                bottom: units.gu(2)
            }

            Image {
                id: team1LogoImage
                source: team1Logo
                width: parent.width
                height: units.gu(5)
                fillMode: Image.PreserveAspectFit
                anchors.horizontalAlignment: parent.horizontalCenter
            }

            Label {
                text: team1Name
                anchors.horizontalAlignment: Text.Center
            }
        }
    }

    // Some more elements and a repeat of the above for the second team
}
Run Code Online (Sandbox Code Playgroud)

问题是,如果team1Logoteam2Logo不是有效的URL,例如团队没有徽标,则Image组件将失败.

我想做的主要是:

if (team1Logo === "") {
    Label {
        // Stuff to make it look good without an image
    }
} else {
    Image {
        source: team1Logo
    }

    Label {
        // Stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

但据我所知,这不是QML的工作原理.

我已经看了一下Loader组件,看起来它可能符合条件,因为我可以source在加载器上设置属性时使用条件,但我无法使它工作.有谁知道如何实现我所描述的?

Tom*_*unn 6

事实证明,实施一个相当简单Loader.例:

Item {
    id: team1Info

    Loader {
        id: team1ItemLoader
        property string name: model.team1Name
        property string logo: model.team1Logo

        source: (logo) ? "TeamLogoItem.qml" : "TeamItem.qml"
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,namelogo然后变得可用内部TeamLogoItem.qmlTeamItem.qml作为属性.


Phr*_*ogz 5

@TommyBrunn 的答案仅在TeamItem.qml未定义property您要传入的任何内容时才有效。这意味着:

  • 你不能property alias在你的组件中使用
  • 您不能为此类属性提供任何默认值

或者,您可以使用setSource()for aLoader将属性值传递给加载的组件:

// ### TeamItem.qml (and TeamLogoItem.qml, similarly)
Label {
  property alias name: text
  property string logo: "qrc:/images/logos/dummy.png"
}    
Run Code Online (Sandbox Code Playgroud)
// ### main.qml
Item {
    id: team1Info

    Loader {
        Component.onCompleted: {
            var qml = model.team1Logo ? "TeamLogoItem.qml" : "TeamItem.qml";
            setSource( qml, { name:model.team1Name, logo:model.team1Logo } )
        }
    }
 }
Run Code Online (Sandbox Code Playgroud)

您还可以根据您正在加载的 QML 选择传入不同的属性值——例如,不将徽标传入 TeamItem.qml。它们不必具有相同的接口。