QML ListView sections from the code
Question:
I am unable to implement listview with sections. I’ve successfully repeated an example from Qt
documentation but there is ListModel
used which works okay, but not a var
.
How it works with example:
ListView {
width: 100
height: 100
id: listview
model: ListModel {
id: animalsModel
ListElement { name: "Ant"; size: "Tiny" }
ListElement { name: "Flea"; size: "Tiny" }
ListElement { name: "Parrot"; size: "Small" }
ListElement { name: "Guinea pig"; size: "Small" }
ListElement { name: "Rat"; size: "Small" }
ListElement { name: "Butterfly"; size: "Small" }
ListElement { name: "Dog"; size: "Medium" }
ListElement { name: "Cat"; size: "Medium" }
ListElement { name: "Pony"; size: "Medium" }
ListElement { name: "Koala"; size: "Medium" }
ListElement { name: "Horse"; size: "Large" }
ListElement { name: "Tiger"; size: "Large" }
ListElement { name: "Giraffe"; size: "Large" }
ListElement { name: "Elephant"; size: "Huge" }
ListElement { name: "Whale"; size: "Huge" }
}
delegate: Text { text: name; font.pixelSize: 18 }
section.property: "size"
section.criteria: ViewSection.FullString
section.delegate: Component {
id: sectionHeading
Rectangle {
width: container.width
height: childrenRect.height
color: "lightsteelblue"
Text {
text: section
font.bold: true
font.pixelSize: 20
}
}
}
}
But when I try to use some model from the code (in my case it is a QVariant
from PyQt5
) it does not work at all:
ListView {
width: 100
height: 100
id: listview
property var m: [
{
name: "Animal",
size: "Big"
},
{
name: "Dog",
size: "Small"
},
{
name: "Cat",
size: "Small"
}
]
model: m
delegate: Text { text: modelData.name; font.pixelSize: 18 }
section.property: "modelData.size"
section.criteria: ViewSection.FullString
section.delegate: Component {
id: sectionHeading
Rectangle {
width: container.width
height: childrenRect.height
color: "lightsteelblue"
Text {
text: section
font.bold: true
font.pixelSize: 20
}
}
}
}
The reason I choose var
here because there is not any other method to receive a model from Python , so any list
or map
from python
needs to be wrapped as QVariant
.
Answers:
From Qt documentation:
model : model
This property holds the model providing data for the list.
The model provides the set of data that is used to create the items in the view. Models can be created directly in QML using ListModel, XmlListModel or VisualItemModel, or provided by C++ model classes. If a C++ model class is used, it must be a subclass of QAbstractItemModel or a simple list.
So you cannot provide an array as a model, it should be one of the objects above.
You can create such model and access it from Python code to add/remove items.
ListView {
width: 100
height: 100
id: listview
delegate: Text { text: name; font.pixelSize: 18 }
model: ListModel { id: listModel }
section.property: "size"
section.criteria: ViewSection.FullString
section.delegate: Component {
id: sectionHeading
Rectangle {
width: container.width
height: childrenRect.height
color: "lightsteelblue"
Text {
text: section
font.bold: true
font.pixelSize: 20
}
}
}
function callFromPython {
listModel.append({name: "Animal",size: "Big"});
listModel.append({name: "Dog",size: "Small"});
listModel.append({name: "Cat",size: "Small"});
}
}
There were a couple of issues with your code snippet:
- Bug: Use
section.property: "size"
(not section:property: "modelData.size"
)
- Warn: Use
font.pointSize: 14
instead of (font.pixelSize: 20
)
- For cross-platform support, including high DPI and retina displays, best to use pointSize over pixelSize
- Warn: Replace
width: 100
and height: 100
with anchors.fill: parent
.
- Avoid pixel measurements whenever we can avoid it
- Info: Use
Frame
and ListView.view.width
for sizing delegates
Frame
gives a padded border to components
- Info: Added
ScrollBar.vertical
Here’s a full working example:
import QtQuick
import QtQuick.Controls
Page {
ListView {
anchors.fill: parent
model:[
{ name: "Animal", size: "Big" },
{ name: "Dog", size: "Small" },
{ name: "Cat", size: "Small" }
]
delegate: Frame {
width: ListView.view.width - 20
Text {
text: modelData.name
font.pointSize: 12
}
}
section.property: "size"
section.delegate: Frame {
width: ListView.view.width - 20
background: Rectangle { color: "lightsteelblue" }
Text {
text: section
font.bold: true
font.pointSize: 14
}
}
ScrollBar.vertical: ScrollBar {
width: 20
policy: ScrollBar.AlwaysOn
}
}
}
You can Try it Online!
I am unable to implement listview with sections. I’ve successfully repeated an example from Qt
documentation but there is ListModel
used which works okay, but not a var
.
How it works with example:
ListView {
width: 100
height: 100
id: listview
model: ListModel {
id: animalsModel
ListElement { name: "Ant"; size: "Tiny" }
ListElement { name: "Flea"; size: "Tiny" }
ListElement { name: "Parrot"; size: "Small" }
ListElement { name: "Guinea pig"; size: "Small" }
ListElement { name: "Rat"; size: "Small" }
ListElement { name: "Butterfly"; size: "Small" }
ListElement { name: "Dog"; size: "Medium" }
ListElement { name: "Cat"; size: "Medium" }
ListElement { name: "Pony"; size: "Medium" }
ListElement { name: "Koala"; size: "Medium" }
ListElement { name: "Horse"; size: "Large" }
ListElement { name: "Tiger"; size: "Large" }
ListElement { name: "Giraffe"; size: "Large" }
ListElement { name: "Elephant"; size: "Huge" }
ListElement { name: "Whale"; size: "Huge" }
}
delegate: Text { text: name; font.pixelSize: 18 }
section.property: "size"
section.criteria: ViewSection.FullString
section.delegate: Component {
id: sectionHeading
Rectangle {
width: container.width
height: childrenRect.height
color: "lightsteelblue"
Text {
text: section
font.bold: true
font.pixelSize: 20
}
}
}
}
But when I try to use some model from the code (in my case it is a QVariant
from PyQt5
) it does not work at all:
ListView {
width: 100
height: 100
id: listview
property var m: [
{
name: "Animal",
size: "Big"
},
{
name: "Dog",
size: "Small"
},
{
name: "Cat",
size: "Small"
}
]
model: m
delegate: Text { text: modelData.name; font.pixelSize: 18 }
section.property: "modelData.size"
section.criteria: ViewSection.FullString
section.delegate: Component {
id: sectionHeading
Rectangle {
width: container.width
height: childrenRect.height
color: "lightsteelblue"
Text {
text: section
font.bold: true
font.pixelSize: 20
}
}
}
}
The reason I choose var
here because there is not any other method to receive a model from Python , so any list
or map
from python
needs to be wrapped as QVariant
.
From Qt documentation:
model : model
This property holds the model providing data for the list.
The model provides the set of data that is used to create the items in the view. Models can be created directly in QML using ListModel, XmlListModel or VisualItemModel, or provided by C++ model classes. If a C++ model class is used, it must be a subclass of QAbstractItemModel or a simple list.
So you cannot provide an array as a model, it should be one of the objects above.
You can create such model and access it from Python code to add/remove items.
ListView {
width: 100
height: 100
id: listview
delegate: Text { text: name; font.pixelSize: 18 }
model: ListModel { id: listModel }
section.property: "size"
section.criteria: ViewSection.FullString
section.delegate: Component {
id: sectionHeading
Rectangle {
width: container.width
height: childrenRect.height
color: "lightsteelblue"
Text {
text: section
font.bold: true
font.pixelSize: 20
}
}
}
function callFromPython {
listModel.append({name: "Animal",size: "Big"});
listModel.append({name: "Dog",size: "Small"});
listModel.append({name: "Cat",size: "Small"});
}
}
There were a couple of issues with your code snippet:
- Bug: Use
section.property: "size"
(notsection:property: "modelData.size"
) - Warn: Use
font.pointSize: 14
instead of (font.pixelSize: 20
)- For cross-platform support, including high DPI and retina displays, best to use pointSize over pixelSize
- Warn: Replace
width: 100
andheight: 100
withanchors.fill: parent
.- Avoid pixel measurements whenever we can avoid it
- Info: Use
Frame
andListView.view.width
for sizing delegatesFrame
gives a padded border to components
- Info: Added
ScrollBar.vertical
Here’s a full working example:
import QtQuick
import QtQuick.Controls
Page {
ListView {
anchors.fill: parent
model:[
{ name: "Animal", size: "Big" },
{ name: "Dog", size: "Small" },
{ name: "Cat", size: "Small" }
]
delegate: Frame {
width: ListView.view.width - 20
Text {
text: modelData.name
font.pointSize: 12
}
}
section.property: "size"
section.delegate: Frame {
width: ListView.view.width - 20
background: Rectangle { color: "lightsteelblue" }
Text {
text: section
font.bold: true
font.pointSize: 14
}
}
ScrollBar.vertical: ScrollBar {
width: 20
policy: ScrollBar.AlwaysOn
}
}
}
You can Try it Online!