Details
-
Bug
-
Resolution: Fixed
-
P1: Critical
-
6.5.3, 6.6
-
None
-
-
https://codereview.qt-project.org/c/qt/qtbase/+/489004/12/src/widgets/widgets/qabstractscrollarea.cpp, 0fa666035 (dev), 6b2cbb3fd (6.8), a6920b9fa (6.7), b920432d7 (tqtc/lts-6.5)
Description
Context
I first made a minimal reproducible example to demonstrate how tables resize infinitely when added to a QVBoxLayout alongside a spacer:
QWidget widget; QVBoxLayout layout(&widget); QTableWidget *tableWidget = new QTableWidget; //random filling to get a size and resizing tableWidget->setColumnCount(6); tableWidget->setRowCount(10); //the dynamic resizing allows the bug to appear tableWidget->setSizeAdjustPolicy(QTableWidget::AdjustToContents); //to make the table actually adjust (expand, in this case, to be precise) tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); layout.addWidget(tableWidget); layout.addStretch(); widget.show(); //to make it flicker automatically //also possible to resize manually to test different sizes widget.resize(tableWidget->minimumSizeHint().width(), widget.height()+tableWidget->height()); QObject::connect(tableWidget->verticalScrollBar(), &QScrollBar::rangeChanged, [tableWidget]() { qDebug()<<tableWidget->sizeHint(); });
Findings
However, after testing different Qt versions, I discovered that it last worked correctly in Qt 6.5.2, which led me to search for what changes were introduced in Qt 6.5.3, and found these:
QTBUG-109326- https://codereview.qt-project.org/c/qt/qtbase/+/489004/12/src/widgets/widgets/qabstractscrollarea.cpp
This bug seems to be caused by a typo (copy-paste error maybe).
Qt 6.5.2:
QSize QAbstractScrollArea::sizeHint() const{ /* preevious code */ const bool vbarHidden = d->vbar->isHidden() || d->vbarpolicy == Qt::ScrollBarAlwaysOff; const bool hbarHidden = d->hbar->isHidden() || d->hbarpolicy == Qt::ScrollBarAlwaysOff; /* next code */ }
Starting from Qt 6.5.3:
QSize QAbstractScrollArea::sizeHint() const{ /* preevious code */ const bool vbarHidden = !d->vbar->isVisibleTo(this) || d->vbarpolicy == Qt::ScrollBarAlwaysOff; // this should be "h" ->V const bool hbarHidden = !d->vbar->isVisibleTo(this) || d->hbarpolicy == Qt::ScrollBarAlwaysOff; /* next code */ }
It checks whether the hScrollbar is visible using vScrollbar. Combine that with the spacer expanding, and it causes the table to shrink, but the hScrollBar will still take space, causing the vertical one to appear (d->vbar->isVisibleTo(this) == true); the size is then "corrected", the vScrollbar disappears. Rinse and repeat.
Suggestions
I added two checks to the unit test from the mentioned bug fix. One for each scrollbar, if it's correctly taken into account by sizeHint. Just comparing the sizeHint with/without the scrollbar. I've also attached a standalone unit test for this specific bug.