Qt / QML-分组和重用元素

时间:2018-09-30 12:59:56

标签: qt qml qt5

有人能为我指出如何最好地组织我的QML的正确方向吗?

目前,对于常见的单个组件,我制作了一个新的QML文件,并将其添加到我的资源下的Common目录中。

例如我的Label.qml

Text{
    width: parent.width * 0.5
    height: parent.height * 0.1
    color: "#ffffff"
    font.underline: true
    font.pointSize: 16
    verticalAlignment: Text.AlignBottom
    horizontalAlignment: Text.AlignLeft
}

然后在我的Form.qml中,我可以这样导入和使用它:

   import "Common"

    Page {

        Label{
            id: username_lbl
            text: "Username"
            anchors.topMargin: parent.height * 0.1
        }

    ...
    }

但是,如果我想将多个组件组合在一起并引用它们以用于连接,该如何做呢?

例如,我想要位于页面底部的一对按钮(下面只是一个示例,不起作用):

所以我想要一个ButtonPair.qml,它有点像这样:

    Button {
        id: left_btn
        width: parent.width * 0.5
        height: parent.height * 0.1

        anchors.bottom: parent.bottom
        anchors.right: parent.right

    }

    Button {
        id: right_btn
        width: parent.width * 0.5
        height: parent.height * 0.1

        anchors.bottom: parent.bottom
        anchors.left: parent.left
    }

然后在我的Form.qml中,我想使用这些按钮,并为每个按钮添加一个事件处理程序:

import "Common"

Page {

    ButtonPair{id: back_forward_buttons}

    Connections {
        target: back_forward_buttons.left_btn
        onClicked: {
            stackView.pop();
    }

    Connections {
        target: back_forward_buttons.right_btn
        onClicked: {
            stackView.push("AnotherPage.qml");
    }

}

我是否需要将ButtonPair包裹在Component中并在页面上使用Loader?如果是,我该如何进入各个左/右按钮,以便绑定到onClicked

2 个答案:

答案 0 :(得分:1)

设计组件时,将其视为黑匣子,该黑匣子具有必须从外部查看的属性和信号。

例如,在您的情况下,ButtonPair必须公开2个信号:一个按下左按钮时,另一个按下右按钮时,我添加的另一件事是2个属性,可以建立按钮的名称。

我看到您已经将按钮的高度设置为父亲高度的10%,应该在下部,如果您想在顶部使用相同的组件?我将不得不创建另一个topButtonPair组件,如果我希望它们在右边,等等。对于在创建组件时不应该在实现中确定大小的问题。在这种情况下,每个按钮必须占据父项的一半。

使用上述方法,我们将获得以下信息:

ButtonPair.qml

import QtQuick 2.0
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11

Item{
    // expose properties and signals
    property string leftname: ""
    property string rightname: ""
    signal leftClicked()
    signal rightClicked()

    // internals
    RowLayout{
        anchors.fill: parent
        spacing: 0
        Button {
            text: leftname
            onClicked: leftClicked()
            Layout.fillWidth: true
            Layout.fillHeight: true
        }
        Button {
            text: rightname
            onClicked: rightClicked()
            Layout.fillWidth: true
            Layout.fillHeight: true
        }
    }
}

注意: 布局的使用是可选的,您可以使用锚点。

现在在页面上使用:

Page {

    // other components

    ButtonPair{
        anchors.bottom: parent.bottom
        height: 0.1*parent.height // <--- Here the height is established
        anchors.left: parent.left
        anchors.right: parent.right
        leftname: "left text"
        rightname: "right text"
        onLeftClicked: console.log("left clicked")
        onRightClicked: console.log("right clicked")
    }
}

答案 1 :(得分:0)

通常,@ eyllanesc采取的黑匣子方法是更好的方法,应尽可能使用它。但是,如果您确实需要从外部访问子项,则可以:

ButtonPair.qml:

Item {
    property alias leftButton: left_btn
    property alias rightButton: right_btn

    // … declarations of left_btn and right_btn as in your question
}

用法:

ButtonPair {
    leftButton {
        onClicked: {
            stackView.pop();
        }
    }
    rightButton {
        onClicked: {
            stackView.push("AnotherPage.qml");
        }
    }
}

您也可以在Connections中使用它。但是,在95%的情况下,您应该像@eyllanesc的方法一样转发属性和信号,这将导致界面更加清晰易读。