QtQuick2 中的 QFormLayout 等效项?

QFormLayout equivalent in QtQuick2?

我正在将基于 QtWidgets 的应用程序移植到 QtQuick2。

我想知道应该使用哪些 QtQuick 布局项。

我卡在 QFormLayout。我根本找不到一个等价物。我能找到的最好的是 GridLayout,但我希望自动生成标签 (like in QFormLayout)。

QHBoxLayout converts to RowLayout
QVBoxLayout converts to ColumnLayout
QGridLayout converts to GridLayout
QFormLayout 转换为 ???

据我所知,QML 中没有 QFormLayout 的等价物。

您必须自己定义组件 Repeater and GridLayout

您可以在此处找到一些详细信息:

一个例子 FormLayout.qml :

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.0

GridLayout {
    id: grid

    // Emitted when text has changed
    signal inputTextChanged(int index, string text)

    columns: 2
    rowSpacing: 5
    columnSpacing: 5

    property var labels: []

    Repeater {
        model: grid.labels
        Text {
            Layout.row: index
            Layout.column: 0
            Layout.preferredWidth: 100
            Layout.preferredHeight: 100
            text: modelData
            verticalAlignment: Text.AlignVCenter
        }
    }

    Repeater {
        model: grid.labels
        TextField {
            Layout.row: index
            Layout.column: 1
            Layout.preferredWidth: 100
            Layout.preferredHeight: 40
            onTextChanged: inputTextChanged(index,text)
        }
    }
}

main.qml :

import QtQuick 2.5
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")


    FormLayout {
        anchors {
            fill: parent
            margins: 5
        }

        labels: ["label1","label2"]
        onInputTextChanged: console.log(index + "/" + text)
    }
}

labels 可以是 any model that qml accept(来自 C++ 的 JS 数组、ListModel 或 AbstractItemModel)。

如果你对GridLayout感到满意,只是缺少自动标签生成,你可以自己创建一些小帮手class,在其中封装Label并持有一个属性 为控件。

// FormControl.qml

import QtQuick 2.0
import QtQuick.Controls 2.0

Item {
    id: root
    property alias label: myLabel

    Label {
        id: myLabel
        parent: root.parent

        Layout.fillHeight: true
        Layout.fillWidth: true

        verticalAlignment: Qt.AlignVCenter

        MouseArea {
            anchors.fill: parent
            onClicked: root.control.forceActiveFocus()
        }
    }

    property Item control

    Row {
        id: content
        parent: myLabel.parent // parent it to myLabel.parent, to make sure, that one is added first.
        children: [control]
    }
}

用法很简单:

import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0

ApplicationWindow {
    id: myWindow
    visible: true
    width: 600
    height: 600
    color: 'white'

    GridLayout {
        columns: 2

        FormControl {
            label.text: 'test1'
            control: ComboBox {
                model: ['hello', 'world', 'and', 'bye']
            }
        }

        FormControl {
            label.text: 'Text'
            control: TextField {
            }
        }

        FormControl {
            label.text: 'Something Long'
            control: TextField {

            }
        }
    }
}

当您在 FormControl.qml 中声明 default property Item control 时,您可以省略 control。然后你可能会 acidently 添加多个控件,其中第一个控件将丢失。

我使用 Row 来受益于隐式高度和宽度,但您也可以使用 Item 并将宽度和高度设置为它的 childrenRect.width/height。但是,我不确定这是否可靠。