Widgets wrapped in QScrollArea do not use up available size

1.3k views Asked by At

Enter: the base code. Creates 25 QPushButtons wrapped in a QWidget with a QVBoxLayout, which (the QWidget) is itself the only child of a top-QVBoxLayout that handles widget placement in our top scroll_area_test-QWidget. The second QWidget wrapping may sound redundant, but will come in handy later.

#include <QVBoxLayout>
#include <QScrollArea>
#include <QWidget>
#include <QPushButton>
#include <QApplication>

/* 
 * This declaration actually lives in its own header file,
 * but for simplicity's sake this code includes it here directly.
 */ 
class scroll_area_test : public QWidget {
  Q_OBJECT

  public:
    scroll_area_test ();
};

scroll_area_test::scroll_area_test () {
  QVBoxLayout *top_layout = new QVBoxLayout (this);

  QWidget *contents = new QWidget (this);
  top_layout->addWidget (contents);

  QVBoxLayout* inner_layout = new QVBoxLayout (contents);

  for (size_t i = 0; i < 25; ++i) {
    QPushButton *tmp_button = new QPushButton (this);
    inner_layout->addWidget (tmp_button);
  }
}

int main (int argc, char **argv) {
  QApplication app (argc, argv);

  scroll_area_test widget;
  widget.show();

  return (app.exec ());
}

This works fine. It produces a window with 25 buttons stashed on top of each other. Given that my display resolution is high enough, I can see the full window. Everything's dandy.

Without QScrollArea

But wait, what if the user's resolution was lower than my own? The window would be too big to fit on their screens! Alas, there is a solution for these kinds of situations. Enter: QScrollArea.

scroll_area_test::scroll_area_test () {
  QVBoxLayout *top_layout = new QVBoxLayout (this);

  QScrollArea *scrolling_area = new QScrollArea (this);
  scrolling_area->setWidgetResizable (true);
  scrolling_area->setFocusPolicy (Qt::NoFocus);
  top_layout->addWidget (scrolling_area);

  QWidget *contents = new QWidget (this);
  //contents->setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);

  QVBoxLayout* inner_layout = new QVBoxLayout (contents);
  //inner_layout->setSizeConstraint (QLayout::SetMinimumSize);

  for (size_t i = 0; i < 25; ++i) {
    QPushButton *tmp_button = new QPushButton (this);
    inner_layout->addWidget (tmp_button);
  }

  scrolling_area->setWidget (contents);
}

I would expect this to not change the layout on my system, since there is ample space to show all widgets.

However, that's the new output:

With QScrollArea

What am I doing wrong? I want the scroll area to resize to its child's size automatically (hence setWidgetResizable (true)), bounded by the maximum window size. This does not seem to be the case here. The containing widget's size is not correctly taken into account and the scroll area thus is a.) smaller in height than it should be and b.) larger in width than it should be, both compared to the look without wrapping the QWidget in QScrollArea.

I've already played around with size constraints and policies (shown by commented-out code), but these did not change anything visually.

N.B.: I experienced this problem in a much more complicated situation, but was able to abstract it to this example.

1

There are 1 answers

2
Pavan Chandaka On

You need to set size policy for your QScrollArea object.

Set the policy fixed both horizontally and vertically, as said below.

QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
scrolling_area->setSizePolicy(sizePolicy);