Reputation: 1210
I want to make a view that looks something like (I left off a column for brevity)
__________
| text |
|__________|
| |headr|
|____|_____|
|text|item1|
| |item2|
| | |
|text|item3|
| |item4|
| |item5|
| |item6|
|____|_____|
and have been trying to do this with a GridLayout. The problem is that I could have potentially many rows. It just depends on my model. So, I want to be able to have a repeater that will repeat the same n elements. However, it seems to only take one component. I would love to repeat one element but that is not how the GridLayout figures out spacing. So, it seems as if this is impossible except using dynamic object creation.
My code for the actual item trying to be repeated is this
Text {
Layout.alignment: Qt.AlignHCenter
text: abbr
color: "#545454"
}
VerticalRule {
Layout.fillHeight: true
}
ColumnLayout {
Repeater {
model: getModel()
Image {}
}
}
VerticalRule {
Layout.fillHeight: true
}
ColumnLayout {
Repeater {
model: getModel()
Image {}
}
}
So, is there any way to do this easily in qml or am I kind of on my own when it comes to this kind of super specific table ish format.
Upvotes: 5
Views: 5367
Reputation: 2118
Add multiple Items as children to a delegate Item and use JavaScript to reparent them to the GridLayout when the delegate Item is completed.
The OP requests a solution that avoids using a wrapping Item, but a wrapping Item affords the cleanest solution to this problem and supports an arbitrary number of columns. Also, I have never seen a solution using a "wrapping Item" -- this is the page that comes up whenever I search for one.
GridLayout {
id: grid
anchors.centerIn: parent
columns: 2
Repeater {
model: [
{ column1: "text1", column2: ["item1","item2"] },
{ column1: "text2", column2: ["item3","item4","item5","item6","item7"] },
{ column1: "text3", column2: ["item8","item9"] },
]
delegate: Item {
objectName: "wrapping_item"
property int rowOffset: 4
Component.onCompleted: {
// reparent all child elements into the grid
while (children.length)
children[0].parent = grid;
}
Text {
objectName: "first_child"
Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.column: 0
Layout.row: index + rowOffset
text: modelData.column1
}
Column {
objectName: "second_child_containing_more_children"
Layout.alignment: Qt.AlignLeft
Layout.column: 1
Layout.row: index + rowOffset
Repeater {
model: modelData.column2
delegate: Text { text: modelData }
}
}
}
}
// same header code as in other answer, just moved out of the way
Text {
text: "text"
Layout.columnSpan: 2
}
Rectangle {
height: 2
color: "blue"
Layout.row: 1
Layout.columnSpan: 2
Layout.fillWidth: true
}
Text {
text: "header"
Layout.row: 2
Layout.column: 1
}
Rectangle {
height: 2
color: "blue"
Layout.row: 3
Layout.columnSpan: 2
Layout.fillWidth: true
}
}
Upvotes: 0
Reputation: 2118
You can do it with the GridLayout; use multiple Repeaters, one for each column in the Gridlayout. The following snippet reproduces your text layout:
GridLayout {
columns: 2
Text {
Layout.columnSpan: 2
Layout.alignment: Qt.AlignLeft
text: 'text'
}
Rectangle {
height: 2
color: "black"
Layout.row: 1
Layout.columnSpan: 2
Layout.fillWidth: true
}
Text {
Layout.column: 1
Layout.row: 2
text: 'header'
}
Rectangle {
height: 2
color: "black"
Layout.row: 3
Layout.columnSpan: 2
Layout.fillWidth: true
}
Repeater {
model: list
Text {
Layout.column: 0
Layout.row: index + 4
Layout.alignment: Qt.AlignTop
text: label
}
}
Repeater {
model: list
Column {
Layout.column: 1
Layout.row: index + 4
Repeater {
model: items
Text { text: item }
}
}
}
ListModel {
id: list
ListElement {
label: 'text1'
items: [
ListElement { item: 'item1' },
ListElement { item: 'item2' }
]
}
ListElement {
label: 'text2'
items: [
ListElement { item: 'item3' },
ListElement { item: 'item4' },
ListElement { item: 'item5' },
ListElement { item: 'item6' },
ListElement { item: 'item7' }
]
}
ListElement {
label: 'text3'
items: [
ListElement { item: 'item8' },
ListElement { item: 'item9' }
]
}
}
}
Upvotes: 7