How to create columns in a QML ListView
Based on a French original.
Here is one way to create a ListView with multiple columns whose widths depend upon the size of the data in the column.
Normally a ListView of Row elements would look like this.
Columns can be created setting the widths in the Row elements.
Getting the text width
Font metrics are not available in QML. However, Text elements can be created dynamically in JavaScript and queried for their width.
// Create temporary Text element
var textElement = Qt.createQmlObject('import Qt 4.7; Text { text: "' + text + '"}',
parent, "calcTextWidth");
// Use textElement.width for the width of the text
// Dispose of temporary element
textElement.destroy()
Creating columns in a ListView
The column widths are calculated for the model with JavaScript, stored in a map with keys by the model element names, and used in the ListView delegate.
main.qml
A simple UI to demonstrate the ListView. A Rectangle element is used as a container simply to give it a color consistent with the colors used for the rows. Note the columnWidths property is used to store the calculated widths, which are used in the delegate.
import Qt 4.7
import "ColumnHelper.js" as ColumnHelper
Rectangle {
width: 620
height: 200
color: "#bebebe"
ListView {
id: list
property variant columnWidths: ColumnHelper.calcColumnWidths(model, list)
anchors.fill: parent
model: MovieModel { }
delegate: MovieItem { }
}
}
ColumnHelper.js
A simple JavaScript function is used to find the maximum width for Text elements of all the data in every column and returns those values in an object keyed by the column name.
var columns = {}
function calcColumnWidths(model, parent)
{
for (var i = 0; i < model.count; +''i)
{
var data = model.get(i)
for (var key in data)
{
if (!columns[key]) {
columns[key] = 0
}
var textElement = Qt.createQmlObject(
'import Qt 4.7;'
'' 'Text {'
+ ' text: "' + data[key] + '" '
+ '}',
parent, "calcColumnWidths")
columns[key] = Math.max(textElement.width, columns[key])
textElement.destroy()
}
}
return columns
}
MovieItem.qml
This is the delegate for the ListView. The columnWidths property of the list is used to set the widths of the columns.
import Qt 4.7
Component {
Item {
id: item
width: parent.width - 15
height: row.height
function altColor(i) {
var colors = [ "#bebebe", "#b7b7b7" ];
return colors[i];
}
Rectangle {
id: background
width: parent.width + 15
height: parent.height
color: altColor(index%2)
}
Row {
id: row
width: parent.width
spacing: 5
Item {
// Indent a little
width: 5
height: 1
}
Text {
width: list.columnWidths['title']
text: model.title
color: "blue"
}
Loader { sourceComponent: columnSeparator; height: parent.height }
Text {
width: list.columnWidths['year']
text: model.year
}
Loader { sourceComponent: columnSeparator; height: parent.height }
Text {
width: list.columnWidths['rank']
text: model.rank
}
Loader { sourceComponent: columnSeparator; height: parent.height }
Text {
width: list.columnWidths['votes']
text: model.votes
}
Loader { sourceComponent: columnSeparator; height: parent.height }
Text {
width: list.columnWidths['composer']
text: model.composer ? model.composer : ""
}
Component {
id: columnSeparator
Rectangle {
width: 1
color: "black"
opacity: 0.3
}
}
}
}
}
MovieModel.qml
Information courtesy of The Internet Movie Database (http://www.imdb.com).
import Qt 4.7
ListModel {
ListElement {
votes: 532564
rank: 9.2
title: "The Shawshank Redemption"
year: 1994
composer: "Newman, Thomas"
}
ListElement {
votes: 419312
rank: 9.1
title: "The Godfather"
year: 1972
composer: "Rota, Nino"
}
ListElement {
votes: 251290
rank: 9.0
title: "The Godfather: Part II"
year: 1974
composer: "Rota, Nino"
}
ListElement {
votes: 225000
rank: 8.9
title: "Inception"
year: 2010
composer: "Zimmer, Hans"
}
ListElement {
votes: 165033
rank: 8.9
title: "Il buono, il brutto, il cattivo."
year: 1966
composer: "Morricone, Ennio"
}
ListElement {
votes: 426752
rank: 8.9
title: "Pulp Fiction"
year: 1994
}
ListElement {
votes: 282473
rank: 8.9
title: "Schindler's List"
year: 1993
composer: "Williams, John"
}
ListElement {
votes: 122919
rank: 8.9
title: "12 Angry Men"
year: 1957
composer: "Hopkins, Kenyon"
}
ListElement {
votes: 219739
rank: 8.8
title: "One Flew Over the Cuckoo's Nest"
year: 1975
composer: "Nitzsche, Jack"
}
ListElement {
votes: 476112
rank: 8.8
title: "The Dark Knight"
year: 2008
composer: "Zimmer, Hans"
}
ListElement {
votes: 283354
rank: 8.8
title: "Star Wars: Episode V - The Empire Strikes Back"
year: 1980
composer: "Williams, John"
}
ListElement {
votes: 371790
rank: 8.8
title: "The Lord of the Rings: The Return of the King"
year: 2003
composer: "Shore, Howard"
}
ListElement {
votes: 98799
rank: 8.8
title: "Shichinin no samurai"
year: 1954
composer: "Hayasaka, Fumio"
}
ListElement {
votes: 326619
rank: 8.7
title: "Star Wars"
year: 1977
composer: "Williams, John"
}
ListElement {
votes: 234582
rank: 8.7
title: "Goodfellas"
year: 1990
}
ListElement {
votes: 170874
rank: 8.7
title: "Casablanca"
year: 1942
composer: "Steiner, Max"
}
}