QML Layout的布局笔记

本文介绍了一个使用QML的GridLayout布局管理器的例子。该示例展示了如何通过GridLayout来组织UI元素,包括Label、TextField和Button等组件,并实现了文件选择功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GridLayout的使用例子

import QtQuick 2.0
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2

Rectangle {
    id: taskPage
    signal  taskAdd(string taskProcess)

    GridLayout{
        anchors.fill: parent //对整个组件布局,需要充满它,否则GridLayout默认是不充满的
        rows: 3
        columns: 6

        Label {
            id: labelTask
            text: "任务程序"
            anchors.verticalCenter: btnBrowser.verticalCenter
            Layout.rowSpan: 1
            Layout.columnSpan: 2
        }
        TextField {
            id: edit
            Layout.fillWidth: true //自动扩展,相当于QWidget的Expanding
            Layout.rowSpan: 1
            Layout.columnSpan: 2
        }
        Button {
            id: btnBrowser
            text: "浏览"
            Layout.rowSpan: 1
            Layout.columnSpan: 2
            onClicked: {
                fileDialog.visible = true;
            }
        }

        Label {
            text: "请选择要添加的任务程序(*.bat 或 *.exe)"
            Layout.rowSpan: 1
            Layout.columnSpan: 6
        }

        Button {
            id: btnBack
            Layout.fillWidth: true
            text: "返回"
            Layout.rowSpan: 1
            Layout.columnSpan: 3
        }
        Button {
            id: btnAdd
            Layout.fillWidth: true
            text: "添加"
            Layout.rowSpan: 1
            Layout.columnSpan: 3
            onClicked: {
                taskPage.taskAdd(edit.text)
            }
        }
    }

    FileDialog {
        id: fileDialog
        title: "Please choose a file"
        folder: shortcuts.home
        onAccepted: {
            edit.text = fileDialog.fileUrl;
            visible: false
        }
        onRejected: {
            visible: false
        }
        Component.onCompleted: visible = false
    }
}

运行结果





// Page1Component.qml import QtQuick import QtQuick.Controls import QtQuick.Layouts import "../../MyComponents" RowLayout { id:root width: 1000 height: 500 Layout.fillWidth: true Layout.fillHeight: true spacing: 10 property string startDate: "2022/05/04" property string endDate: "2022/05/04" property string startTime: "00:00:00" property string endTime: "00:00:00" property bool isStaTable: true property var customTable: null property var flickable: null // 左侧区域 Rectangle { id: leftPanel Layout.fillWidth: true Layout.fillHeight: true Layout.preferredWidth: parent.width / 2 // 宽度占一半 radius: 16 color: "#0CFFFFFF" border.color: "#19FFFFFF" border.width: 1 // 左侧内容 ColumnLayout { anchors.fill: parent anchors.leftMargin: 32 // 左边距 anchors.rightMargin: 32 // 右边距 anchors.topMargin: 0 // anchors.bottomMargin: 32// spacing: 10 // 👇 第1行:固定展示文本 Item { Layout.preferredHeight: 48 Layout.fillWidth: true Text { text: qsTr("Beverage Statistics") font.pixelSize: 20 color: "#BA9E88" // anchors.verticalCenter: parent.verticalCenter // 垂直居中 anchors.centerIn: parent } } // 👇 第2行:快速定位时间 RowLayout { Layout.fillWidth: true Layout.preferredHeight: 52 // 或者根据字体大小设定合适的高度 spacing: 10 // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Quick Select") font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } // 右侧按钮 CustomTimerButton { id: todayButton normalText: "Today" countdownSeconds: 0 normalBackgroundColor: "#333435" borderColor: "#4A4A4A" width: 100 height: 40 onCountdownFinished: { // 获取当前时间 var now = new Date() var yesterday = new Date(now) yesterday.setDate(yesterday.getDate() - 1) // 设置开始日期和时间(昨天) customStartDateButton.setDateFromJSDate(yesterday) customStartTimeutton.setTimeFromJSDate(yesterday) // 设置结束日期和时间(今天) customEndDateButton.setDateFromJSDate(now) customEndTimeButton.setTimeFromJSDate(now) } } CustomTimerButton { id: weekButton normalText: "1 Week" countdownSeconds: 0 normalBackgroundColor: "#333435" borderColor: "#4A4A4A" width: 100 height: 40 onCountdownFinished: { var now = new Date() var oneWeekAgo = new Date(now) oneWeekAgo.setDate(oneWeekAgo.getDate() - 7) // 设置开始日期和时间(一周前) customStartDateButton.setDateFromJSDate(oneWeekAgo) customStartTimeutton.setTimeFromJSDate(oneWeekAgo) // 设置结束日期和时间(今天) customEndDateButton.setDateFromJSDate(now) customEndTimeButton.setTimeFromJSDate(now) } } CustomTimerButton { id: monthButton normalText: "1 Month" countdownSeconds: 0 normalBackgroundColor: "#333435" borderColor: "#4A4A4A" width: 100 height: 40 onCountdownFinished: { var now = new Date() var oneMonthAgo = new Date(now) oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1) // 设置开始日期和时间(一个月前) customStartDateButton.setDateFromJSDate(oneMonthAgo) customStartTimeutton.setTimeFromJSDate(oneMonthAgo) // 设置结束日期和时间(今天) customEndDateButton.setDateFromJSDate(now) customEndTimeButton.setTimeFromJSDate(now) } } } // 👇 第3行:日期选择 RowLayout { Layout.fillWidth: true Layout.preferredHeight: 40 // 或者根据字体大小设定合适的高度 spacing: 10 // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Date Select") font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } // 开始日期 CustomDateSelectButton { id: customStartDateButton displayDate: "2022/05/04" width: 152 height: 40 onDateChanged: function(date){ startDate = date // console.log("z外部接收到日期变化:", date) } } // - Item { Layout.fillWidth: false Text { text: qsTr("-") // font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } //结束日期 CustomDateSelectButton { id: customEndDateButton displayDate: "2022/05/05" width: 152 height: 40 onDateChanged: function(date){ endDate = date // console.log("z外部接收到日期变化:", date) } } } // 👇 第4行:time选择 RowLayout { Layout.fillWidth: true Layout.preferredHeight: 40 // 或者根据字体大小设定合适的高度 spacing: 10 // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Time Select") font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } // 开始time CustomTimeSelectButton { id: customStartTimeutton width: 152 height: 40 displayTime: "00:00:00" onSelectTimeChanged: function(time){ startTime = time // console.log("z外部接收到time变化:", time) // totalCoffeeCups = "1" } } // - Item { Layout.fillWidth: false Text { text: qsTr("-") // font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } //结束time CustomTimeSelectButton { id: customEndTimeButton displayTime: "01:00:00" width: 152 height: 40 onSelectTimeChanged: function(time){ endTime = time // console.log("z外部接收到time变化:", time) // totalCoffeeCups = "1" } } } // 👇 第5行:横线 Rectangle { height: 1 color: "#333435" Layout.fillWidth: true } // 👇 第6行:数据库检索动作 RowLayout { Layout.fillWidth: true Layout.preferredHeight: 52 // 或者根据字体大小设定合适的高度 spacing: 10 // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Check") font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } CustomSwitch { id: funcSwitch Layout.fillWidth: false Layout.fillHeight: false Layout.alignment: Qt.AlignRight | Qt.AlignVCenter Layout.rightMargin: 40 checked: root.isStaTable onCheckedChanged: { root.isStaTable = checked // console.log("funcSwitch checked: ", checked," isStaTable: ", root.isStaTable) } } // 右侧按钮 CustomTimerButton { id: checkButton normalText: "refresh" countdownSeconds: 0 normalBackgroundColor: "#986d4d" borderColor: "#986d4d" width: 100 height: 40 function deepCompare(a, b) { return JSON.stringify(a) === JSON.stringify(b); } property var lastStartTime: "0" property var lastEndTime: "0" onCountdownFinished: { //进行数据库检索 var startDateTime = startDate + " " + startTime; var endDateTime = endDate + " " + endTime; OperateOptionVM.beveragesStatisticsVM.fetchData(startDateTime,endDateTime) if (root.customTable) { var newData; if(root.isStaTable){ console.log("getStaCellData"); newData = OperateOptionVM.beveragesStatisticsVM.getStaCellData(); } else{ console.log("getLogCellData"); newData = OperateOptionVM.beveragesStatisticsVM.getLogCellData(); } console.log("获取数据成功,准备更新表格"); root.customTable.cellData = newData; console.log("获取数据成功,已更新表格"); // 👇 强制更新 Flickable 内容高度,不然布局就会混乱 if (flickable && flickable.contentHeight > 0) { flickable.contentHeight = 0; flickable.contentHeight = customTable.height; } } } } } // 👇 第7行:横线 Rectangle { height: 1 color: "#333435" Layout.fillWidth: true } // 👇 第8行:查询结果 RowLayout { Layout.fillWidth: true Layout.preferredHeight: 52 // 或者根据字体大小设定合适的高度 spacing: 10 // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Total Cups :")//机器开机以来的总杯数 font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } Item { Layout.fillWidth: true Text { text: OperateOptionVM.beveragesStatisticsVM.totalCups//机器开机以来的总杯数 font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Count Cups :")//统计杯数 font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } Item { Layout.fillWidth: true Text { text: OperateOptionVM.beveragesStatisticsVM.countCups//统计的总杯数 font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } } // 👇 第9行:横线 Rectangle { height: 1 color: "#333435" Layout.fillWidth: true } // 👇 第10行:固定展示文本 Item { Layout.preferredHeight: 36 Layout.fillWidth: true Text { text: qsTr("Estimated Consumption") font.pixelSize: 16 color: "#BA9E88" anchors.verticalCenter: parent.verticalCenter // 垂直居中 // anchors.centerIn: parent } } // 👇 第11行:查询结果- RowLayout { Layout.fillWidth: true Layout.preferredHeight: 52 // 或者根据字体大小设定合适的高度 spacing: 10 // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Beans(G) :")//统计豆量 font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } Item { Layout.fillWidth: true Text { text: OperateOptionVM.beveragesStatisticsVM.beansUsed font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Powder(G) :")//统计粉量 font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } Item { Layout.fillWidth: true Text { text: OperateOptionVM.beveragesStatisticsVM.powderUsed font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } } // 👇 第12行:查询结果- RowLayout { Layout.fillWidth: true Layout.preferredHeight: 20 // 或者根据字体大小设定合适的高度 spacing: 10 // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Milk(L) :")//统计奶量 font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } Item { Layout.fillWidth: true Text { text: OperateOptionVM.beveragesStatisticsVM.milkUsed font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } // 左侧文本 Item { Layout.fillWidth: true Text { text: qsTr("Water(L) :")//统计水量 font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } Item { Layout.fillWidth: true Text { text: OperateOptionVM.beveragesStatisticsVM.waterUsed font.pixelSize: 16 color: "white" anchors.verticalCenter: parent.verticalCenter } } } } } // 右侧区域 Rectangle { id: rightPanel Layout.fillWidth: true Layout.fillHeight: true Layout.preferredWidth: parent.width / 2 // 宽度占另一半 radius: 16 color: "#0CFFFFFF" border.color: "#19FFFFFF" border.width: 1 Loader { id: tablePanelLoader // Layout.fillWidth: true//切忌这里使用fillWidth,会导致子组件的Flickable无法加载 // Layout.fillHeight: true width: parent.width height: parent.height sourceComponent: root.isStaTable ? page1Component : page0Component } Component { id: page0Component Flickable { id: flickable width: parent.width//切忌这里使用fillWidth height: parent.height contentWidth: customTable.width contentHeight: customTable.height clip: true ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded } ScrollBar.horizontal: ScrollBar { policy: ScrollBar.AsNeeded } Component.onCompleted: { root.flickable = flickable } ColumnLayout { anchors.fill: parent anchors.leftMargin: 20 // 左边距 anchors.rightMargin: 20 // 右边距 anchors.topMargin: 20 // anchors.bottomMargin: 20// spacing: 10 anchors.centerIn: parent CustomTableView2 { id: customTable width: 440 height: Math.max(1, OperateOptionVM.beveragesStatisticsVM.rows * 40) cellBorderColor: "transparent" // Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter // anchors.centerIn: parent rows: OperateOptionVM.beveragesStatisticsVM.rows columns: OperateOptionVM.beveragesStatisticsVM.columns cellSpacing: 0 columnWidths: [160, 160, 120] componentMap: { "columnHeaderComponent": columnHeaderComponent, "rowHeaderComponent": rowHeaderComponent, "defaultComponent": defaultComponent } Component.onCompleted: { root.customTable = customTable } Component { id: columnHeaderComponent ColumnHeader { textColor: "#BA9E88" disText: parent.cellData ? parent.cellData.text : "defaut" backgroundColor: "transparent" borderBottomColor: "#333435" disPixelSize: 16 } } Component { id: rowHeaderComponent RowHeader { disText: parent.cellData ? parent.cellData.text : "defaut" description: parent.cellData ? parent.cellData.description : "defaut" } } Component { id: defaultComponent ColumnHeader { textColor: "white" disText: parent.cellData ? parent.cellData.text : "defaut" backgroundColor: "transparent" borderBottomColor: "#333435" disPixelSize: 12 } } } } } } Component { id: page1Component Flickable { id: flickable2 width: parent.width//切忌这里使用fillWidth height: parent.height contentWidth: customTable.width contentHeight: customTable.height clip: true ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded } ScrollBar.horizontal: ScrollBar { policy: ScrollBar.AsNeeded } Component.onCompleted: { root.flickable = flickable2 } ColumnLayout { anchors.fill: parent anchors.leftMargin: 20 // 左边距 anchors.rightMargin: 20 // 右边距 anchors.topMargin: 20 // anchors.bottomMargin: 20// spacing: 10 anchors.centerIn: parent CustomTableView2 { id: customTable2 width: 440 height: Math.max(1, OperateOptionVM.beveragesStatisticsVM.rows * 40) cellBorderColor: "transparent" // Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter // anchors.centerIn: parent rows: OperateOptionVM.beveragesStatisticsVM.rows columns: OperateOptionVM.beveragesStatisticsVM.columns cellSpacing: 0 columnWidths: [140, 60, 60, 60, 60, 60] componentMap: { "columnHeaderComponent": columnHeaderComponent, "rowHeaderComponent": rowHeaderComponent, "defaultComponent": defaultComponent } Component.onCompleted: { root.customTable = customTable2 } Component { id: columnHeaderComponent ColumnHeader { textColor: "#BA9E88" disText: parent.cellData ? parent.cellData.text : "defaut" backgroundColor: "transparent" borderBottomColor: "#333435" disPixelSize: 16 } } Component { id: rowHeaderComponent RowHeader { disText: parent.cellData ? parent.cellData.text : "defaut" description: parent.cellData ? parent.cellData.description : "defaut" } } Component { id: defaultComponent ColumnHeader { textColor: "white" disText: parent.cellData ? parent.cellData.text : "defaut" backgroundColor: "transparent" borderBottomColor: "#333435" disPixelSize: 12 } } } } } } } } 这是一份qml代码,可以看到我用到了两张表,实际上一张表就可以解决问题,唯一不同的就是列宽,请帮我合为一个表
最新发布
07-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值