TableView in QML

Take a look at how the TableView works in Qt6 with QML. If we refer to the example from the official documentation, we find this code:

 import QtQuick 2.14
 import Qt.labs.qmlmodels 1.0

 TableView {
     anchors.fill: parent
     columnSpacing: 1
     rowSpacing: 1
     clip: true

     model: TableModel {
         TableModelColumn { display: "name" }
         TableModelColumn { display: "color" }

         rows: [
             {
                 "name": "cat",
                 "color": "black"
             },
             {
                 "name": "dog",
                 "color": "brown"
             },
             {
                 "name": "bird",
                 "color": "white"
             }
         ]
     }

     delegate: Rectangle {
         implicitWidth: 100
         implicitHeight: 50
         border.width: 1

         Text {
             text: display
             anchors.centerIn: parent
         }
     }
 }

It produces this:

If we add more columns to the model in the following manner:

model: TableModel {
                    TableModelColumn { display: "name" }
                    TableModelColumn { display: "color" }
                    TableModelColumn { display: "feet" }
                    TableModelColumn { display: "fly" }

                    rows: [
                        {
                            "name": "cat",
                            "color": "black",
                            "feet": "four",
                            "fly": "no"
                        },
                        {
                            "name": "dog",
                            "color": "brown",
                            "feet": "four",
                            "fly": "no"
                        },
                        {
                            "name": "bird",
                            "color": "white",
                            "feet": "two",
                            "fly": "yes"
                        }
                    ]
                }

we have:

In this approach, not all elements are visible because each cell is of the same size. While this uniformity can be visually appealing, it may not always be practical. Next, let’s see how we can add a custom header and adjust the cells to have widths based on the size of the elements within them.

Let’s start with the header:

           HorizontalHeaderView {
                id: horizontalHeader
                anchors.left: tableView.left
                anchors.top: parent.top
                syncView: tableView
                clip: true
                model: ["Name", "Color", "Feet", "Fly"]
                delegate:
                    Rectangle {
                        implicitWidth: txt.width + dp(5)
                        implicitHeight: txt.height + dp(5)
                        color: "darkgray"
                        AppText {
                            id: txt
                            text: modelData
                            anchors.centerIn: parent
                            color: "white"
                        }

                }

            }

First, we attach the header to the left side of the table and set the syncView to the tableView. This ensures synchronization between the table and the header, meaning each header column aligns with its corresponding column in the tableView. Next, we define the labels for the header. Finally, we see in the delegate how to display the header’s cells.

The tableView:

            TableView {
                id: tableView
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: horizontalHeader.bottom
                anchors.bottom: parent.bottom
                columnSpacing: 1
                rowSpacing: 1
                clip: true
                contentWidth: parent.width
                columnWidthProvider: column => { return -1; }
                model: // is the same

                delegate: Rectangle {
                    implicitWidth: Math.max(horizontalHeader.columnWidth(column), txtRow.width) + dp(5)
                    implicitHeight: txtRow.height + dp(10)
                    border.color: "darkgray"
                    Text {
                        id: txtRow
                        text: display
                        anchors.centerIn: parent
                    }
                }
            }

The model remains the same as previously mentioned and is not included here. Regarding the positioning, the top of the table is anchored to the bottom of the header, as one would expect. The code enabling cell width to be based on the element’s width within the cell is as follows: columnWidthProvider: column => { return -1; }. The columnWidthProvider property expects a function that returns the width for a column. However, if it returns -1, the size is automatically calculated based on the size of the element in the cell.

Another important aspect to note is the use of the following code:

implicitWidth: Math.max(horizontalHeader.columnWidth(column), txtRow.width) + dp(5)

Why is this necessary? It ensures that if the text in the header of a column is wider than the text in the data cells, the size of the header remains readable. This code calculates the maximum width between the header and the row text, and then adds a small margin (dp(5)) for better visual spacing.

The final result is:

“Note: English is not my native language, so please excuse any errors. I would appreciate your assistance in correcting them.”

share this post with friends

Picture of Nicola De filippo

Nicola De filippo

I'm a software engineer who adds to the passion for technologies the wisdom and the experience without losing the wonder for the world. I love to create new projects and to help people and teams to improve

Leave a comment

Your email address will not be published. Required fields are marked *

Who I am

I'm a software engineer who adds to the passion for technologies the wisdom and the experience without losing the wonder for the world. I love to create new projects and to help people and teams to improve.

Follow Me Here

Get The Latest Updates

Periodically receive my super contents on coding and programming

join the family;)

Recent Posts