Виджеты, завернутые в QScrollArea, не используют доступный размер

Введите: базовый код. Создает 25 QPushButtons, завернутый в QWidget с QVBoxLayout, который (QWidget) сам по себе является единственным дочерним элементом top-QVBoxLayout, который обрабатывает размещение виджета в нашем верхнем scroll_area_test-QWidget. Вторая обертка QWidget может показаться излишней, но она пригодится позже.

#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 ());
}

Это прекрасно работает. Он создает окно с 25 кнопками, спрятанными друг над другом. Учитывая, что разрешение моего экрана достаточно высокое, я могу видеть все окно. Все денди.

Без QScrollArea

Но подождите, а что, если разрешение пользователя было ниже моего? Окно было бы слишком большим, чтобы поместиться на их экранах! Увы, для таких ситуаций есть решение. Введите: 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);
}

Я ожидаю, что это не изменит макет в моей системе, поскольку места достаточно для отображения всех виджетов.

Однако это новый вывод:

С QScrollArea

Что я делаю неправильно? Я хочу, чтобы область прокрутки автоматически изменялась до размера своего дочернего элемента (отсюда setWidgetResizable (true)), ограниченного максимальным размером окна. Кажется, здесь это не так. Размер содержащего виджета не учитывается правильно, и поэтому область прокрутки а) меньше по высоте, чем должна быть, и б) больше по ширине, чем должна быть, и то, и другое по сравнению с внешним видом без переноса QWidget в QScrollArea.

Я уже поиграл с ограничениями размера и политиками (показаны закомментированным кодом), но визуально это ничего не изменило.

N.B.: Я столкнулся с этой проблемой в гораздо более сложной ситуации, но смог абстрагироваться от этого примера.


person Ionic    schedule 14.09.2017    source источник


Ответы (1)


Вам необходимо установить политику размера для вашего объекта QScrollArea.

Установите политику фиксированной как по горизонтали, так и по вертикали, как указано ниже.

QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
scrolling_area->setSizePolicy(sizePolicy);
person Pavan Chandaka    schedule 15.09.2017
comment
Спасибо. Это делает кое-что интересное, поскольку сохраняет ширину, как в исходном примере, но высота все еще слишком мала. Также при этом изменение размера окна возможно, но бесполезно, так как область прокрутки не растет вместе с родительским виджетом. Учитывая, что размер области прокрутки всегда должен изменяться вместе с родителем, использование для нее политики фиксированного размера не кажется хорошей идеей. - person Ionic; 15.09.2017
comment
Что произойдет, если вы установите политику Фиксированная только для горизонтальной, а другую — для вертикальной? Как правило, есть более интересные флаги размера, такие как QSizePolicy::Expanding, которые могут помочь или не помочь: doc.qt.io/qt-5/qsizepolicy.html#Policy-enum - person uli42; 15.04.2021