QML布局系統主要分為三大類:錨布局、定位器布局、布局管理器。
一、錨布局(Anchors)
通過定義元素與其他元素或父容器的錨點關系實現精確定位,支持動態調整。
核心特性
屬性? | ?作用? | ?示例? |
---|---|---|
anchors.left | 左邊緣對齊目標元素 | anchors.left: parent.left |
anchors.right | 右邊緣對齊目標元素 | anchors.right: parent.right |
anchors.top | 頂部對齊目標元素 | anchors.top: parent.top |
anchors.bottom | 底部對齊目標元素 | anchors.bottom: parent.bottom |
?組合屬性? | ||
anchors.fill | 填充整個目標元素(通常為父容器) | anchors.fill: parent |
anchors.centerIn | 在目標元素中居中 | anchors.centerIn: parent |
?邊距控制? | ||
anchors.margins | 統一設置四周邊距 | anchors.margins: 10 |
*Margin | 單獨設置某方向邊距(如leftMargin ) | anchors.leftMargin: 15 |
適用場景?:需要精確相對定位的UI元素(如表單控件對齊)。?
代碼示例:
//錨布局Rectangle {// 填充整個區域anchors.left: parent.leftcolor: "#f9e370"width: 300height: 300Rectangle {// 左上角anchors.top: parent.topanchors.topMargin: 5anchors.left: parent.leftanchors.leftMargin: 5color: "#ef2929"width: 50height: 50}Rectangle {// 右上角anchors.top: parent.topanchors.topMargin: 5anchors.right: parent.rightanchors.rightMargin: 5color: "#8ae234"width: 50height: 50}Rectangle {// 左下角anchors.bottom: parent.bottomanchors.bottomMargin: 5anchors.left: parent.leftanchors.leftMargin: 5color: "#204a87"width: 50height: 50}Rectangle {// 右下角anchors.bottom: parent.bottomanchors.bottomMargin: 5anchors.right: parent.rightanchors.rightMargin: 5color: "#5c3566"width: 50height: 50}Rectangle {// 居中anchors.centerIn: parentcolor: "#ad7fa8"width: 50height: 50}Rectangle {// 中上anchors.top: parent.topanchors.topMargin: 5anchors.horizontalCenter: parent.horizontalCentercolor: "#fcaf3e"width: 50height: 50}Rectangle {// 左中anchors.left: parent.leftanchors.leftMargin: 5anchors.verticalCenter: parent.verticalCentercolor: "#729fcf"width: 50height: 50}Rectangle {// 右中anchors.right: parent.rightanchors.rightMargin: 5anchors.verticalCenter: parent.verticalCentercolor: "#555753"width: 50height: 50}Rectangle {// 中下anchors.bottom: parent.bottomanchors.bottomMargin: 5anchors.horizontalCenter: parent.horizontalCentercolor: "#ce5c00"width: 50height: 50}}
運行結果:
二、定位器布局(Positioners)
自動排列子元素,無需手動計算位置,適合規則排列。
四大定位器類型?
?類型? | ?排列方向? | ?關鍵屬性? | ?特點? |
---|---|---|---|
Row | 水平排列 | spacing | 子項等寬或按內容自適應 |
Column | 垂直排列 | spacing | 子項等高或按內容自適應 |
Grid | 網格排列 | rows /columns | 支持跨行/列,自動換行 |
Flow | 流式排列 | flow | 根據容器寬度自動換行 |
屬性
定位器類型? | ?核心屬性? | ?屬性說明? | ?布局特點? | ?典型應用場景? | ?代碼示例? |
---|---|---|---|---|---|
?行定位器 (Row)? | spacing | 子項水平間距(像素) | 從左向右水平排列子項 | 水平導航欄、工具欄按鈕組 |
|
layoutDirection | 排列方向:Qt.LeftToRight (默認)或Qt.RightToLeft (從右向左) | 支持反向布局 | RTL語言界面適配 | layoutDirection: Qt.RightToLeft | |
?列定位器 (Column)? | spacing | 子項垂直間距(像素) | 從上向下垂直排列子項 | 設置菜單、垂直列表 |
|
自動尺寸約束 | 寬度繼承最寬子項,高度自適應 | 無需顯式設置尺寸 | 動態內容容器 | 默認行為 | |
?網格定位器 (Grid)? |
| 強制指定行/列數量(默認自適應) | 從左到右、從上到下矩陣排列 | 表單布局、圖標網格 |
|
flow | 排列順序:Grid.LeftToRight (先行后列)或Grid.TopToBottom (先列后行) | 控制填充優先級 | 特殊順序布局 | flow: Grid.TopToBottom | |
| 獨立設置行/列間距(覆蓋spacing ) | 支持非均衡間距 | 復雜表格布局 | rowSpacing: 5; columnSpacing: 12 | |
?流式定位器 (Flow)? | flow | 換行方向:Flow.LeftToRight (水平流)或Flow.TopToBottom (垂直流) | 自動換行/換列 | 瀑布流布局、標簽云 |
|
padding | 容器內邊距(像素) | 子項與容器邊緣的距離 | 帶邊距的響應式布局 | padding: 15 | |
spacing | 統一控制水平和垂直間距 | 簡化間距設置 | 緊湊型布局 | spacing: 10 |
適用場景?:規則排列的列表、圖標網格或色塊組。
代碼示例:
//定位器布局Rectangle {// 填充整個區域anchors.right: parent.rightcolor: "#c5fd30"width: 300height: 300//水平Row {anchors.top: parent.topanchors.topMargin: 3anchors.left: parent.leftanchors.leftMargin: 3spacing: 3Repeater {model: 4Rectangle {width: 30height: 30color: {switch(index) {case 0: return "red"case 1: return "green"case 2: return "blue"case 3: return "gray"}}}}}//垂直Column {anchors.bottom: parent.bottomanchors.bottomMargin: 3anchors.left: parent.leftanchors.leftMargin: 3spacing: 3Repeater {model: 4Rectangle {width: 30height: 30color: {switch(index) {case 0: return "red"case 1: return "green"case 2: return "blue"case 3: return "gray"}}}}}//網格Grid {anchors.top: parent.topanchors.topMargin: 3anchors.right: parent.rightanchors.rightMargin: 3columns: 3spacing: 3Repeater {model: 14Rectangle {width: 30height: 30color: getRectColor()function getRectColor() {if (Positioner.index % 4 === 0)return 'red'else if (Positioner.index % 4 === 1)return 'green'else if (Positioner.index % 4 === 2)return 'blue'elsereturn 'gray'}}}}//流式Flow {anchors.bottom: parent.bottomanchors.bottomMargin: 3anchors.right: parent.rightanchors.rightMargin: 3width: 162spacing: 3Repeater {model: 14Rectangle {width: 30height: 30color: getRectColor()function getRectColor() {if (Positioner.index % 4 === 0)return 'red'else if (Positioner.index % 4 === 1)return 'green'else if (Positioner.index % 4 === 2)return 'blue'elsereturn 'gray'}}}}}
運行結果:
三、布局管理器(Layout Managers)
提供響應式布局能力,需導入QtQuick.Layouts
模塊,支持動態拉伸和約束控制。
核心類型及功能?
?類型? | ?方向? | ?特有附加屬性? | ?功能? |
---|---|---|---|
RowLayout | 水平 | Layout.fillWidth | 子項按比例填充剩余寬度 |
ColumnLayout | 垂直 | Layout.preferredHeight | 控制子項高度優先級 |
GridLayout | 網格 | Layout.rowSpan | 支持跨行/列布局 |
StackLayout | 堆疊 | currentIndex | 類似選項卡切換顯示不同子項 |
屬性
布局類型? | ?核心屬性? | ?屬性說明? | ?示例代碼? |
---|---|---|---|
?行布局 (RowLayout)? | spacing | 子項水平間距(像素) |
|
Layout.fillWidth | 子項是否填充剩余寬度(true/false) | Rectangle {Layout.fillWidth: true} | |
?列布局 (ColumnLayout)? | spacing | 子項垂直間距(像素) |
|
Layout.fillHeight | 子項是否填充剩余高度(true/false) | Rectangle {Layout.fillHeight: true} | |
?網格布局 (GridLayout)? | columns /rows | 強制指定列/行數(默認自適應) |
|
flow | 排列方向:LeftToRight(默認)或TopToBottom | flow: GridLayout.TopToBottom | |
?堆棧布局 (StackLayout)? | currentIndex | 當前可見子項的索引(默認0) |
|
count | 子項總數(只讀屬性) | onCountChanged: console.log(count) | |
Layout.fillWidth/Height | 子項默認填充整個布局區域(true) | Rectangle {Layout.fillWidth: false // 禁用默認填充} |
代碼示例:
//布局管理器Rectangle {anchors.left: parent.leftanchors.bottom: parent.bottomcolor: "#5ccbf6"width: 300height: 300//水平RowLayout {anchors.top: parent.topanchors.topMargin: 5anchors.left: parent.leftanchors.leftMargin: 5width: 100Rectangle {color: 'red'Layout.fillWidth: trueLayout.minimumWidth: 50Layout.preferredWidth: 50Layout.maximumWidth: 100Layout.minimumHeight: 25Text {anchors.centerIn: parenttext: parent.width + 'x' + parent.height}}Rectangle {color: "green"Layout.fillWidth: falseLayout.minimumWidth: 25Layout.preferredWidth: 100Layout.preferredHeight: 50Text {anchors.centerIn: parenttext: parent.width + 'x' + parent.height}}}//垂直ColumnLayout {anchors.bottom: parent.bottomanchors.bottomMargin: 5anchors.left: parent.leftanchors.leftMargin: 5height: 150Rectangle {color: 'red'Layout.fillHeight: trueLayout.minimumHeight: 50Layout.preferredWidth: 75Layout.preferredHeight: 75Layout.maximumWidth: 100Layout.maximumHeight: 100Text {anchors.centerIn: parenttext: parent.width + 'x' + parent.height}}Rectangle {color: 'green'Layout.fillHeight: falseLayout.minimumWidth: 100Layout.preferredWidth: 100Layout.preferredHeight: 50Text {anchors.centerIn: parenttext: parent.width + 'x' + parent.height}}}//網格GridLayout {anchors.top: parent.topanchors.topMargin: 5anchors.right: parent.rightanchors.rightMargin: 5flow: GridLayout.LeftToRightheight: 120columns: 3Rectangle {color: 'red'Layout.columnSpan: 1width: 30height: 30}Rectangle {color: 'gray'Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenterwidth: 30height: 30}Rectangle {color: 'blue'Layout.rowSpan: 2width: 30height: 30}Rectangle {color: 'green'width: 30height: 30}}//堆疊StackLayout {anchors.right: parent.rightanchors.bottom: parent.bottomcurrentIndex: parseInt(textEdit.text)height: 120width: 120Rectangle {color: 'red'}Rectangle {color: 'green'}Text {text: "Text"}Image {source: "file:///home/li/圖片/1.png"}}TextEdit {id: textEditanchors.centerIn: parentwidth: 80height: 20text: qsTr("0")}}
運行結果:
四、定位器布局 vs 布局管理器對比表?
特性? | ?定位器布局(Positioners)? | ?布局管理器(Layout Managers)? |
---|---|---|
?核心類型? | Row , Column , Grid , Flow | RowLayout , ColumnLayout , GridLayout |
?子元素尺寸調整? | ?固定子元素原始尺寸,不自動縮放 | 動態調整子元素大小(填充/約束空間) |
?排列方式? | 簡單順序排列(水平/垂直/網格) | 高級自適應排列(支持權重/對齊/跨行跨列) |
?響應式布局? | ?窗口縮放時元素位置固定不變 | 自動根據容器尺寸調整子項布局 |
?附加屬性? | 僅基礎屬性(如spacing ) | 豐富約束屬性(fillWidth /alignment /minimumHeight 等) |
?適用場景? | 靜態元素排列(圖標欄、固定菜單) | 動態表單、可伸縮界面、復雜自適應布局 |
五、完整代碼示例
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.14Window {visible: truewidth: 640height: 640title: qsTr("布局")//錨布局Rectangle {// 填充整個區域anchors.left: parent.leftcolor: "#f9e370"width: 300height: 300Rectangle {// 左上角anchors.top: parent.topanchors.topMargin: 5anchors.left: parent.leftanchors.leftMargin: 5color: "#ef2929"width: 50height: 50}Rectangle {// 右上角anchors.top: parent.topanchors.topMargin: 5anchors.right: parent.rightanchors.rightMargin: 5color: "#8ae234"width: 50height: 50}Rectangle {// 左下角anchors.bottom: parent.bottomanchors.bottomMargin: 5anchors.left: parent.leftanchors.leftMargin: 5color: "#204a87"width: 50height: 50}Rectangle {// 右下角anchors.bottom: parent.bottomanchors.bottomMargin: 5anchors.right: parent.rightanchors.rightMargin: 5color: "#5c3566"width: 50height: 50}Rectangle {// 居中anchors.centerIn: parentcolor: "#ad7fa8"width: 50height: 50}Rectangle {// 中上anchors.top: parent.topanchors.topMargin: 5anchors.horizontalCenter: parent.horizontalCentercolor: "#fcaf3e"width: 50height: 50}Rectangle {// 左中anchors.left: parent.leftanchors.leftMargin: 5anchors.verticalCenter: parent.verticalCentercolor: "#729fcf"width: 50height: 50}Rectangle {// 右中anchors.right: parent.rightanchors.rightMargin: 5anchors.verticalCenter: parent.verticalCentercolor: "#555753"width: 50height: 50}Rectangle {// 中下anchors.bottom: parent.bottomanchors.bottomMargin: 5anchors.horizontalCenter: parent.horizontalCentercolor: "#ce5c00"width: 50height: 50}}//定位器布局Rectangle {// 填充整個區域anchors.right: parent.rightcolor: "#c5fd30"width: 300height: 300//水平Row {anchors.top: parent.topanchors.topMargin: 3anchors.left: parent.leftanchors.leftMargin: 3spacing: 3Repeater {model: 4Rectangle {width: 30height: 30color: {switch(index) {case 0: return "red"case 1: return "green"case 2: return "blue"case 3: return "gray"}}}}}//垂直Column {anchors.bottom: parent.bottomanchors.bottomMargin: 3anchors.left: parent.leftanchors.leftMargin: 3spacing: 3Repeater {model: 4Rectangle {width: 30height: 30color: {switch(index) {case 0: return "red"case 1: return "green"case 2: return "blue"case 3: return "gray"}}}}}//網格Grid {anchors.top: parent.topanchors.topMargin: 3anchors.right: parent.rightanchors.rightMargin: 3columns: 3spacing: 3Repeater {model: 14Rectangle {width: 30height: 30color: getRectColor()function getRectColor() {if (Positioner.index % 4 === 0)return 'red'else if (Positioner.index % 4 === 1)return 'green'else if (Positioner.index % 4 === 2)return 'blue'elsereturn 'gray'}}}}//流式Flow {anchors.bottom: parent.bottomanchors.bottomMargin: 3anchors.right: parent.rightanchors.rightMargin: 3width: 162spacing: 3Repeater {model: 14Rectangle {width: 30height: 30color: getRectColor()function getRectColor() {if (Positioner.index % 4 === 0)return 'red'else if (Positioner.index % 4 === 1)return 'green'else if (Positioner.index % 4 === 2)return 'blue'elsereturn 'gray'}}}}}//布局管理器Rectangle {anchors.left: parent.leftanchors.bottom: parent.bottomcolor: "#5ccbf6"width: 300height: 300//水平RowLayout {anchors.top: parent.topanchors.topMargin: 5anchors.left: parent.leftanchors.leftMargin: 5width: 100Rectangle {color: 'red'Layout.fillWidth: trueLayout.minimumWidth: 50Layout.preferredWidth: 50Layout.maximumWidth: 100Layout.minimumHeight: 25Text {anchors.centerIn: parenttext: parent.width + 'x' + parent.height}}Rectangle {color: "green"Layout.fillWidth: falseLayout.minimumWidth: 25Layout.preferredWidth: 100Layout.preferredHeight: 50Text {anchors.centerIn: parenttext: parent.width + 'x' + parent.height}}}//垂直ColumnLayout {anchors.bottom: parent.bottomanchors.bottomMargin: 5anchors.left: parent.leftanchors.leftMargin: 5height: 150Rectangle {color: 'red'Layout.fillHeight: trueLayout.minimumHeight: 50Layout.preferredWidth: 75Layout.preferredHeight: 75Layout.maximumWidth: 100Layout.maximumHeight: 100Text {anchors.centerIn: parenttext: parent.width + 'x' + parent.height}}Rectangle {color: 'green'Layout.fillHeight: falseLayout.minimumWidth: 100Layout.preferredWidth: 100Layout.preferredHeight: 50Text {anchors.centerIn: parenttext: parent.width + 'x' + parent.height}}}//網格GridLayout {anchors.top: parent.topanchors.topMargin: 5anchors.right: parent.rightanchors.rightMargin: 5flow: GridLayout.LeftToRightheight: 120columns: 3Rectangle {color: 'red'Layout.columnSpan: 1width: 30height: 30}Rectangle {color: 'gray'Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenterwidth: 30height: 30}Rectangle {color: 'blue'Layout.rowSpan: 2width: 30height: 30}Rectangle {color: 'green'width: 30height: 30}}//堆疊StackLayout {anchors.right: parent.rightanchors.bottom: parent.bottomcurrentIndex: parseInt(textEdit.text)height: 120width: 120Rectangle {color: 'red'}Rectangle {color: 'green'}Text {text: "Text"}Image {source: "file:///home/li/圖片/1.png"}}TextEdit {id: textEditanchors.centerIn: parentwidth: 80height: 20text: qsTr("0")}}}
運行結果: