Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Calculate TableView height according to Image in delegate



  • I have a TableView with the following output:

    f2cc7453-140d-42b6-9009-bfe6f00e4b4c-image.png

    Item {
        property string picture
        
        //...
    
        id: root
        Rectangle {
            id: rect
            anchors.fill: parent
            border.width: 1
            border.color: "black"
        }
    
        Image {
            id: image
            anchors.centerIn: parent
            source: root.picture.length > 0 ? "data:image/png;base64," + root.picture : ""
            fillMode: Image.PreserveAspectFit
            sourceSize.width: rect.width - rect.border.width * 2
            sourceSize.height: rect.height - rect.border.height * 2
        }
    
        //...
    }
    

    So I would have expected the Image fits in the rectangle but it does not.

    The TableView looks like this:

    Item {
        id: root
        
        //...
        
        HorizontalHeaderView {
            id: horizontalHeaderView
            syncView: tableView
            anchors.left: tableView.left
            model: [qsTr("Id"), qsTr("Question"), qsTr("Answer 1"), qsTr(
                    "Answer 2"), qsTr("Answer 3"), qsTr("Answer 4"), qsTr(
                    "Correct Answer"), qsTr("Picture")]
        }
        TableView {
            id: tableView
            width: parent.width
            height: parent.height - horizontalHeaderView.height
            anchors.top: horizontalHeaderView.bottom
            boundsBehavior: Flickable.StopAtBounds
    
            reuseItems: true
            clip: true
            property var columnWidths: [60, 220, 220, 220, 220, 220, 100, 140]
            columnWidthProvider: function (column) {
                return columnWidths[column]
            }
    
            model: questionsProxyModel
    
            delegate: DelegateChooser {
                id: chooser
    
                //... More DelegateChoices here for the other columns but not 
                //.. interesting for the issue here
                DelegateChoice {
                    column: 7
                    delegate: PictureDelegate {
                        id: pictureDelegate
                        width: tableView.columnWidthProvider(column)
                        picture: model.picture
                    }
                }
            }
            ScrollBar.vertical: ScrollBar {}
        }
    }
    
    

    So in the TableView I provide the width to each delegate via columnWidthProvider which works fine.

    The height is calculated automatically according to the content of the childs. This for example makes sure all the text always fits:

    a167dac0-0785-4e24-a37c-499b216aff5f-image.png

    Now how can I take the heigth the Image in the delegate needs to proper scale into account?





  • @LeLev Fixed it I actually used AspectFit. I only used Crop for testing. With fit it does not exceed the width but ignores the height of the rectangle



  • One Idea I have:

    Is it possible to provide a minimum height to the view ?

    I know the width the delegate of the picture cell will have. Out of that I could calculate how much height the picture would need and maybe could supply it to the view?



  • @sandro4912 said in Calculate TableView height according to Image in delegate:

    PictureDelegate

    Are you setting the height of your PictureDelegate Item? Set that to the height of your picture.



  • @fcarney

    I tried that but it freezes the app when I go to the picture:

    Item {
    //....
        height: image.height // set height here
    
    //...
    
        Image {
            id: image
    
            anchors.centerIn: parent
            source: root.picture.length > 0 ? "data:image/png;base64," + root.picture : ""
            fillMode: Image.PreserveAspectFit
            sourceSize.width: rect.width - rect.border.width * 2
            sourceSize.height: rect.height - rect.border.height * 2
        }
    

    A solution I got via PM from @LeLev is omit soureSize complete and add width relative to parent width:

    Image {
        id: image
    
        width: parent.width - rect.border.width * 2
    
        anchors.centerIn: parent
        source: root.picture.length > 0 ? "data:image/png;base64," + root.picture : ""
        fillMode: Image.PreserveAspectFit
    
        Component.onCompleted: console.log(parent.width)
    }
    

    That works perflectly. It was just to simple to come up with it :(



  • Unfortunately I was wrong even with the last approach I still have issues like this:

    f0c779c6-256b-455e-962e-2f028966b7d0-image.png

    Here the Image is again over the borders

    If you like to check the full code here:
    https://github.com/SandroWissmann/Quiz



  • Image {
            id: image
    
            anchors.centerIn: parent
            source: root.picture.length > 0 ? "data:image/png;base64," + root.picture : ""
            fillMode: Image.PreserveAspectFit
            sourceSize.width: rect.width - rect.border.width * 2
            sourceSize.height: rect.height - rect.border.height * 2
        }
    

    Where do you set the height of your image? Not sourceSize.height, but height. sourceSize only affects memory allocation of the image.



  • @fcarney

    I don't set the height I only provide the width from ListView.

    The ListView should render to the maxHeight needed since heightWidthProvider is not set. So that all delegates can be displayed properly.

    The solution to this issue Is replacing the root directly with the rectangle like this:

    Rectangle {
    //...
       color: "transparent"
       border.width: 1
       border.color: "black"
       id: root
    
       Image {
           id: image
    
           anchors.fill: parent
           anchors.margins: root.border.width
           source: root.picture.length > 0 ? "data:image/png;base64," + root.picture : ""
           fillMode: Image.PreserveAspectFit
       }
    

Log in to reply