Замечания по установке размеров виджетам

Пользовательский интерфейс, куда же без него?...

Как заставить отображаться виджеты как нам надо , а не как кому-то хочется?..

Постскриптум: сразу смотрите в сторону отложенной (delayed) отрисовки виджетов по таймеру. Это сэкономит много времени.

Виджеты и компоновщики

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

Компоновщики это QLayout и наследники от него.

Они указывают куда расширять/сжимать элементы окна при изменении размеров самого окна или конкретных элементов в частности. Например названия QVBoxLayout и QHBoxLayout говорят сами за себя.

Каждый виджет должен быть завернут в один из компоновщиков (layout). В этом случае виджету будет указано куда он может изменять свои размеры.

В каком случае надо вообще говоря изменять размеры виджету?

Представим , что вы потянули за край окна мышкой. Начинает изменяться размер окна. 

Это то, что видит пользователь. На самом деле по факту как все работает: возникают события от операционной системы, а именно нажатие кнопки мышки, перемещение курсора мышки, отжатие кнопки мышки. Конечно эти события должен обрабатывать виджет, над которым двигается мышка.

Важный нюанс в том, что события от ОС всегда получает "главный" обработчик событий. Это тот об'ект, который вертит QEventLoop в данный момент . 

Обычно это QApplication. Далее главный обработчик транслирует события подчинённым окнам и они и обрабатывают эти события самостоятельно в своем коде.

Например некое окно, над которым работает мышка видит нажатие мышки и перетаскивание своей рамки в сторону. Окно устанавливает себе новый размер и делает updateGeometry().

Потом вызывается отрисовка update (paint). И тут важный нюанс отрисовка происходит отложенно по событию таймера.То есть по последующему  событию от ОС.

Если видимость виджетов меняется программно из кода, то есть важный нюанс который надо учитывать: QMdiSubWindow, QTabWidget и возможно еще кто-то не подстраивают свой размер корректно под содержание внутри себя, о чем можно почитать в параллельных страницах сайта (это конечно не 100 процентов правда, но проблемка та еще).

QTabWidget Проблемы с уменьшением размера.

QMdiSubWindow проблема с изменением размера под содержание.

Ходим хороводы вокруг основных параметров настройки размеров виджетов в ui формах и пытаемся разобраться кто есть ху.

sizeHint рекомендуемые размеры виджета. Вычисляются по умолчанию на основании некоторых рнкомендуемых размеров каждого виджета. Можно и очень даже иногда нужно переопределять.

baseSize базовые пропорции элемента, по умолчанию 0,0.

QMinimumSize элемента по умолчанию 0,0. Если задать QMinimumSize, то виджет будет строго не меньше этих размеров. В правильно скомпонованных окнах QMinimumSize обычно не приходится использовать.

QMaximumSize виджета. По умолчанию 11111..,11111...(что-то очень большое). Можно жестко ограничить максимальный размер виджета. Но это тоже не очень хорошая идея.

Как ничинается открытие любого окна?

Первое , что мы имеем сначала это само окно, когда у него еще нет никаких элементов и компоновщиков. Но у него уже может быть вычислен size на основании sizeHint, на стадии работы в ui форме через вызов adjustSize для всего контента окна.

Далее в конструкторе происходит создание контента окна.

Создание наполнения окна происходит последовательно , как у вас прописано в конструкторе.

Может показаться , что у окна над ним нет компоновщика. Но на самом деле, это не так.

Например в описании QMdiSubWindow сказано, что QMdiSubWindow имеет свой встроенный layout, в который включен титл бар и область для содержимого (central area).

QMdiSubWindow represents a top-level window in a QMdiArea, and consists of a title bar with window decorations, an internal widget, and (depending on the current style) a window frame and a size grip. QMdiSubWindow has its own layout, which consists of the title bar and a center area for the internal widget.

Самый первый вопрос , который возникает в голове у каждого начинающего прогера, это как растянуть или сжать окно точно под контент внутри него.

Есть прекрасная функция adjustSize. И после нее вызываем updateGeometry.

adjustSize пересчитывает все размеры потомков нашего окна на основании их sizePolicy и sizeHint.

Есть нюанс - функции setSizeHint не существует, то есть чтобы получить требуемое значение sizeHint ее можно только переопределить в наследуемом классе (функция sizeHint виртуальная).

Интересно , что для многих виджетов sizeHint можно определить на стадии разработки макета ui.

Дело в том, что у всех элементов QLineEdit, QLabel, QPushButton и т.д. - есть политики размера по умолчанию.

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

Далее представим ситуацию , что пользователь изменил (увеличил/уменьшил) системный шрифт Windows. В результате после перезапуска ваша программа после adjustSize опять адаптирует размер окна под содержание. Бониссимо!

Кстати в Qt Creator на ui формах можно попробовать adjustSize непосредственно интерактивно.

Мораль такая , что надо как можно меньше пытаться устанавливать размеры явно.

Постскриптум: позднее разбираясь в исходном коде Qt оказалось, что Троли для отрисовки часто предварительно создают таймер, применяют новые размеры виджета через updateGeometry и потом уже по событию таймера отрисовывают виджет update.