How do I adjust a QTableView height according to contents?
Asked Answered
T

3

6

In my layout, my dynamically generated QTableViews seem to get resized to only show one row. I want to have the container of the table views to have a scrollbar instead of the individual table views, which should show full contents.

Trigg answered 25/2, 2017 at 16:42 Comment(0)
T
12

Qt doesn't have anything built in for this apparently, you need to calculate and set the size manually.

This is how I'm doing it for vertical sizing (Qt 5.8). You might want to add setMaximumHeight/width.

To develop it further, it should check for presence of a horizontal scrollbar before adding that to the size. This suffices for my usage though.

Edit 2018-03: You may want to call tableView->resizeRowsToContents(); before this function to have the sizes actually correspond to actual heights of contents and add checks for visibility as per other response.

Edit 2024-03: Added tableView->frameWidth() * 2 as per comments.

void verticalResizeTableViewToContents(QTableView *tableView) {
    int rowTotalHeight = 0;

    // Calculate the total height of all visible rows.
    int rowCount = tableView->verticalHeader()->count();
    for (int i = 0; i < rowCount; ++i) {
        if (!tableView->verticalHeader()->isSectionHidden(i)) {
            rowTotalHeight += tableView->verticalHeader()->sectionSize(i);
        }
    }

    // Add the height of the horizontal scrollbar if it is visible.
    if (!tableView->horizontalScrollBar()->isHidden()) {
        rowTotalHeight += tableView->horizontalScrollBar()->height();
    }

    // Add the height of the horizontal header if it is visible.
    if (!tableView->horizontalHeader()->isHidden()) {
        rowTotalHeight += tableView->horizontalHeader()->height();
    }

    // Factor in the frame width for the top and bottom borders.
    int frameWidth = tableView->frameWidth() * 2;

    // Set the minimum height required to display the rows, header, scrollbar, and frame borders without clipping.
    tableView->setMinimumHeight(rowTotalHeight + frameWidth);
}
Trigg answered 25/2, 2017 at 16:42 Comment(2)
Could this need the addition of the value of tableView->frameWidth() * 2? Seems like it.Stallfeed
@LouisLangholtz Thank you for your comment. Indeed frameWidth needs to be added.Saving
I
9

@savolai Thank you very much for your code, it works well for me. I just do additional checks:

void verticalResizeTableViewToContents(QTableView *tableView)
{
    int rowTotalHeight=0;

    // Rows height
    int count=tableView->verticalHeader()->count();
    for (int i = 0; i < count; ++i) {
        // 2018-03 edit: only account for row if it is visible
        if (!tableView->verticalHeader()->isSectionHidden(i)) {
            rowTotalHeight+=tableView->verticalHeader()->sectionSize(i);
        }
    }

    // Check for scrollbar visibility
    if (!tableView->horizontalScrollBar()->isHidden())
    {
         rowTotalHeight+=tableView->horizontalScrollBar()->height();  
    }

    // Check for header visibility
    if (!tableView->horizontalHeader()->isHidden())
    {
         rowTotalHeight+=tableView->horizontalHeader()->height();  
    }
    tableView->setMinimumHeight(rowTotalHeight);
}
Ilsa answered 7/5, 2018 at 15:30 Comment(0)
R
2

The answers above work like a charm. Adding a Python3 version:

from PyQt5.QtWidgets import QTableWidget


def calc_table_height(table: QTableWidget) -> int:
    """Calculate table height."""
    res = 0
    for i in range(table.verticalHeader().count()):
        if not table.verticalHeader().isSectionHidden(i):
            res += table.verticalHeader().sectionSize(i)
    if table.horizontalScrollBar().isHidden():
        res += table.horizontalScrollBar().height()
    if not table.horizontalHeader().isHidden():
        res += table.horizontalHeader().height()
    return res


def vertical_resize_table_to_content(table: QTableWidget) -> None:
    """Resize table height to content."""
    content_height = calc_table_height(table)
    table.setMaximumHeight(content_height)
Ramble answered 10/8, 2023 at 18:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.