Details
-
Bug
-
Resolution: Done
-
P3: Somewhat important
-
5.12.2
-
None
-
-
6c4dc722cb9bf765904feefff4fb00bdb0b3dc9f (qt/qtbase/dev) 07901558cdd5967549104f1ae80b0be85f328260 (qt/tqtc-qtbase/5.15) 45af046be7a2251284c923e52d42d7b6c7790026 (qt/qtbase/6.2)
Description
Sometimes, preferred height increases when width increases. For example:
+-----+ +--------+ |AA BB| |AA BB CC| |AA BB| |AA BB CC| |CC DD| | CC| |CC DD| |DD | |CC DD| |DD | +-----+ |DD | +--------+
With such widgets, QScrollArea may go back and forth on whether a vertical scrollbar should be shown and cause it to blink nonstop. This reproduces the problem:
#include <QApplication> #include <QScrollArea> #include <QWidget> class Square : public QWidget { public: int heightForWidth(int width) const override { return width; } }; int main(int argc, char **argv) { QApplication app(argc, argv); Square *square = new Square(); QSizePolicy policy = square->sizePolicy(); policy.setHeightForWidth(true); square->setSizePolicy(policy); QScrollArea *area = new QScrollArea(); area->setWidget(square); area->setWidgetResizable(true); area->resize(501, 499); area->show(); return app.exec(); }
Here's a patch that could fix it:
diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp --- a/src/widgets/widgets/qscrollarea.cpp +++ b/src/widgets/widgets/qscrollarea.cpp @@ -194,16 +194,35 @@ void QScrollAreaPrivate::updateScrollBar if (resizable) { if ((widget->layout() ? widget->layout()->hasHeightForWidth() : widget->sizePolicy().hasHeightForWidth())) { - QSize p_hfw = p.expandedTo(min).boundedTo(max); - int h = widget->heightForWidth( p_hfw.width() ); - min = QSize(p_hfw.width(), qMax(p_hfw.height(), h)); + QSize hfw = m.expandedTo(min).boundedTo(max); + QSize min2 = QSize(hfw.width(), qMax(hfw.height(), widget->heightForWidth(hfw.width()))); + + if (m.expandedTo(min2) == m && m.boundedTo(max) == m) { + p = m; // no scroll bars needed + min = min2; + } else { + hfw = p.expandedTo(min).boundedTo(max); + min2 = QSize(hfw.width(), qMax(hfw.height(), widget->heightForWidth(hfw.width()))); + + if (vbarpolicy != Qt::ScrollBarAsNeeded + || p.width() <= m.width() - vbar->sizeHint().width() + || min2.boundedTo(max).height() <= p.height()) { + min = min2; + } else { + p.setWidth(m.width() - vbar->sizeHint().width()); + hfw = p.expandedTo(min).boundedTo(max); + min = QSize(hfw.width(), qMax(hfw.height(), widget->heightForWidth(hfw.width()))); + } + } + } else { + if (m.expandedTo(min) == m && m.boundedTo(max) == m) + p = m; // no scroll bars needed } + } else { + if (m.expandedTo(widget->size()) == m) + p = m; // no scroll bars needed } - if ((resizable && m.expandedTo(min) == m && m.boundedTo(max) == m) - || (!resizable && m.expandedTo(widget->size()) == m)) - p = m; // no scroll bars needed - if (resizable) widget->resize(p.expandedTo(min).boundedTo(max)); QSize v = widget->size();
Attachments
Issue Links
- resulted in
-
QTBUG-97811 QScrollArea performance regression
- Closed
For Gerrit Dashboard: QTBUG-92958 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
346157,7 | Recalculate the height when scrollbar needs to be displayed | dev | qt/qtbase | Status: ABANDONED | +1 | 0 |
375740,3 | Reduce the width of a hfw-widget if scrollbar would be flipping | dev | qt/qtbase | Status: MERGED | +2 | 0 |
376121,2 | Reduce the width of a hfw-widget if scrollbar would be flipping | 6.2 | qt/qtbase | Status: MERGED | +2 | 0 |
376125,2 | Reduce the width of a hfw-widget if scrollbar would be flipping | tqtc/lts-5.15 | qt/tqtc-qtbase | Status: MERGED | +2 | 0 |