QML 如何使用单个 Repeater 向 GridLayout 中添加多个元素
单个Repeater向GridLayout添加多元素实现方案
核心问题说明
Repeater默认仅支持单个委托根元素,如果将多个控件包裹在同一个Item中作为委托,该Item只会占据GridLayout的单个单元格,GridLayout无法对内部控件做独立的行列尺寸适配,也就实现不了全局对齐的效果,这也是包装Item方案不受青睐的核心原因。
推荐实现方案(Qt 5.15及以上版本)
Qt 5.15开始支持多实例委托,无需包裹Item,直接在委托中定义多个控件,将嵌套生成的颜色块的父指定为GridLayout,即可让所有控件作为GridLayout的直接子元素,自动适配行列尺寸,完整实现代码如下:
import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 Window { visible: true width: 600 height: 300 title: "GridLayout多元素填充示例" GridLayout { id: mainGrid anchors.fill: parent margins: 20 columns: 4 rowSpacing: 15 columnSpacing: 20 Repeater { model: [ // 业务JSON模型 { name: "February:", types: [ { name: "R-1", size: 24, color: "red" }, { name: "O--2", size: 16, color: "orange" }, { name: "Y---3", size: 8, color: "yellow" }, ] }, { name: "March:", types: [ { name: "G-1", size: 24, color: "green" }, ] }, { name: "April:", types: [ { name: "B-1", size: 24, color: "blue" }, { name: "I--2", size: 16, color: "indigo" }, { name: "V---3", size: 8, color: "violet" }, ] }, ] delegate: Component { // 月份标签,固定在每行第一列 Text { Layout.row: index Layout.column: 0 text: modelData.name font.bold: true font.pixelSize: 16 } // 嵌套Repeater生成对应行的颜色块 Repeater { model: modelData.types parent: mainGrid // 关键:父节点指定为GridLayout,直接作为网格子元素 delegate: Rectangle { Layout.row: parent.index // 取外层Repeater的行号 Layout.column: index + 1 // 从第二列开始排列 width: 80 height: 40 color: modelData.color radius: 4 Text { anchors.centerIn: parent text: modelData.name font.pixelSize: modelData.size color: "white" } } } } } } }
低版本Qt兼容方案(Qt 5.14及以下)
如果使用的Qt版本不支持多实例委托,可以通过动态创建控件的方式实现,委托使用不可见的空Item作为根节点,在实例化完成后动态创建所有控件添加到GridLayout中,核心代码片段如下:
delegate: Item { visible: false // 委托根节点不参与渲染 Component.onCompleted: { // 创建月份标签 Qt.createQmlObject(` import QtQuick 2.14 Text { font.bold: true font.pixelSize: 16 } `, mainGrid, { "Layout.row": index, "Layout.column": 0, "text": modelData.name }) // 循环创建颜色块 for(let i = 0; i < modelData.types.length; i++) { const type = modelData.types[i] Qt.createQmlObject(` import QtQuick 2.14 Rectangle { radius: 4 Text { anchors.centerIn: parent color: "white" } } `, mainGrid, { "Layout.row": index, "Layout.column": i + 1, "width": 80, "height": 40, "color": type.color, "Text.text": type.name, "Text.font.pixelSize": type.size }) } } }
实现效果

内容的提问来源于stack exchange,提问作者pixelgrease
相关产品推荐
相关产品推荐

