Search code examples
c++qtlayoutqml

QML wrapped TableView element behaves different from non-wrapped one


I'm having some troubles getting the QML type TableView to behave correctly when wrapping it inside another item. The problem is that creating a reuseable type basically forces one to use an Item wrapper to have the *HeaderView types in the same .qml file. Here is the rather simple code, a test-model for some data can be taken from the official TableView documentation.

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import TableModel

Window {  
    width: 600
    height: 480
    visible: true

    // This item wrapper changes TableView behavior
    Item {
        width: 600
        height: 250
    // --------------------------------------------

        TableView {
            id: tableView
            anchors.fill: parent
            topMargin: horizontalHeader.implicitHeight
            leftMargin: verticalHeader.implicitWidth
            columnSpacing: 1
            rowSpacing: 1
            clip: true

            model: TableModel {}

            delegate: Rectangle {
                implicitWidth: 150
                implicitHeight: 25
                Text {
                    text: display
                }
            }
        }

        HorizontalHeaderView {
            id: horizontalHeader
            syncView: tableView
        }

        VerticalHeaderView {
            id: verticalHeader
            syncView: tableView
        }
    // --------------------------------------------
    }
    // --------------------------------------------
}

Without the Item wrapper (see comments in code) my TableView looks as expected: TableView without Item wrapper

But once wrapped inside an Item the horizontal and vertical headers get placed over the actual table. TableView with Item wrapper

For some odd reason this displacement is only relevant for the very first rendering of the table. Once I drag the data from the table around a little (I guess activating the "Flickable" inherited type?) the data suddenly snaps into position and is displayed correctly outside of the headers.


Solution

  • Apparently it wasn't a good idea to use anchors.fill: parent when trying to attach the *HeaderViews. Once I got rid of that line and simply anchored all views to each other (horizontal to top, vertical to left) it works.

    Item {  
        implicitWidth: 600
        implicitHeight: 250
    
        TableView {
            id: tableView
            implicitWidth: parent.implicitWidth
            implicitHeight: parent.implicitHeight
            anchors.top: horizontalHeader.bottom
            anchors.left: verticalHeader.right
            columnSpacing: 1
            rowSpacing: 1
            clip: true
    
            model: TableModel {}
    
            delegate: Rectangle {
                implicitWidth: 150
                implicitHeight: 25
                Text {
                    text: display
                }
            }
        }
    
        HorizontalHeaderView {
            id: horizontalHeader
            anchors.left: verticalHeader.right
            clip: true
            syncView: tableView
        }
    
        VerticalHeaderView {
            id: verticalHeader
            anchors.top: horizontalHeader.bottom        
            clip: true        
            syncView: tableView
        }    
    }
    

    Note thougt that in the official Qt docs using anchors inside layouts is explicitly listed as "Don'ts". My guess is that they mean don't use anchors between layout elements or parents of the layout, not don't anchor two elements inside a single layout cell.