Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-92958

Blinking scrollbar with QScrollArea and edge cases.

    XMLWordPrintable

Details

    • Linux/X11
    • 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

          For Gerrit Dashboard: QTBUG-92958
          # Subject Branch Project Status CR V

          Activity

            People

              vhilshei Volker Hilsheimer
              pochang Pochang Chen
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes