Search code examples
qtuser-interfaceqtableview

How do I adjust a QTableView height according to contents?


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.


Solution

  • 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);
    }