загадочное adjustSize

adjustSize делает расчет размеров виджета, со  всеми его вложенными виджетами.

Обратите внимание, что в ui формах adjustSize может вызвать только для главного топового виджета (например QDialog). А точнее еще можно делать для QTabWindget например и возможно еще для некоторых объектов, но далеко не для всех.

Если для этих виджетов не выбрать ни один тип компоновщика (Layout Horizontally, Layout Vertically, QFormLayout, QGridLayout) они будут помечены красным знаком (остановка запрещена).

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

Компоновщик есть у каждого виджета,  расположен он над виджетом, как бы является его хозяином.

фотка 1

В двух словах adjustSize обходит все дочерние виджеты и вычисляет суммарный их sizeHint() и в конце (это важно) делает resize c указанием этого размера.

Вообще говоря размеры по умолчанию, получаемые через sizeHint, не являются мягко говоря оптимальными. Это некие средние статистические значения.

Но sizeHint() виджетов (и компоновщиков) мы можем переопределять в наследниках! Именно так мы и управляем размерами виджетов.

То есть после adjustSize будет вызвано событие QResizeEvent.

Примечание: в обработчиках событий (типа QResizeEvent) не надо вызывать adjustSize, иначе может произойти зацикливание.

void QWidget::adjustSize()
{
    Q_D(QWidget);
    ensurePolished();
    QSize s = d->adjustedSize();

    if (d->layout)
        d->layout->activate();

    if (s.isValid())
        resize(s);
}

Комментарии из кода разработчиков Qt:

Adjusts the size of the widget to fit its contents.

This function uses sizeHint() if it is valid, i.e., the size hint's width and height are != 0. Otherwise, it sets the size to the children rectangle that covers all child widgets (the union of all child widge rectangles).

For windows, the screen size is also taken into account. If the sizeHint() is less than (200, 100) and the size policy is {QSizePolicy::Expanding} {expanding}, the window will be at least (200, 100). The maximum size of a window is 2/3 of the screen's width and height.
see sizeHint(), childrenRect().

void QWidget::ensurePolished() const
{
    Q_D(const QWidget);

    const QMetaObject *m = metaObject();
    if (m == d->polished)
        return;
    d->polished = m;

    QEvent e(QEvent::Polish);
    QCoreApplication::sendEvent(const_cast(this), &e);

    // polish children after 'this'
    QList children = d->children;
    for (int i = 0; i < children.size();   i) {
        QObject *o = children.at(i);
        if(!o->isWidgetType())
            continue;
        if (QWidget *w = qobject_cast(o))
            w->ensurePolished();
    }

    if (d->parent && d->sendChildEvents) {
        QChildEvent e(QEvent::ChildPolished, const_cast(this));
        QCoreApplication::sendEvent(d->parent, &e);
    }
}

Ensures that the widget has been polished by QStyle (i.e., has a proper font and palette).

QWidget calls this function after it has been fully constructed but before it is shown the very first time. You can call this function if you want to ensure that the widget is polished before doing an operation, e.g., the correct font size might be needed in the widget's sizeHint() reimplementation. Note that this function is called from the default implementation of sizeHint().

Polishing is useful for final initialization that must happen after all constructors (from base classes as well as from subclasses) have been called.

If you need to change some settings when a widget is polished, reimplement event() and handle the QEvent::Polish event type.

Note: The function is declared const so that it can be called from other const functions (e.g., sizeHint()).

По смыслу кода метода ensurePolished получается, что просто происходит генерация события QEvent::Polish для самого виджета и всех подчинённых ему виджетов. В общем надо смотреть и как обрабатывается событие  QEvent::Polish во разных виджетах и тогда станет всё ясно.

Ещё похоже смысл ensurePlished в том, чтобы учесть индивидуальные свойства виджета (при отрисовке) фонт, палитру и т.д.

QSize QWidgetPrivate::adjustedSize() const
{
    Q_Q(const QWidget);

    QSize s = q->sizeHint();

    if (q->isWindow()) {
        Qt::Orientations exp;
        if (layout) {
            if (layout->hasHeightForWidth())
                s.setHeight(layout->totalHeightForWidth(s.width()));
            exp = layout->expandingDirections();
        } else
        {
            if (q->sizePolicy().hasHeightForWidth())
                s.setHeight(q->heightForWidth(s.width()));
            exp = q->sizePolicy().expandingDirections();
        }
        if (exp & Qt::Horizontal)
            s.setWidth(qMax(s.width(), 200));
        if (exp & Qt::Vertical)
            s.setHeight(qMax(s.height(), 100));
#if defined(Q_WS_X11)
        QRect screen = QApplication::desktop()->screenGeometry(q->x11Info().screen());
#else // all others
        QRect screen = QApplication::desktop()->screenGeometry(q->pos());
#endif
#if defined (Q_WS_WINCE) || defined (Q_OS_SYMBIAN)
        s.setWidth(qMin(s.width(), screen.width()));
        s.setHeight(qMin(s.height(), screen.height()));
#else
        s.setWidth(qMin(s.width(), screen.width()*2/3));
        s.setHeight(qMin(s.height(), screen.height()*2/3));
#endif
        if (QTLWExtra *extra = maybeTopData())
            extra->sizeAdjusted = true;
    }

    if (!s.isValid()) {
        QRect r = q->childrenRect(); // get children rectangle
        if (r.isNull())
            return s;
        s = r.size()   QSize(2 * r.x(), 2 * r.y());
    }

    return s;
}

Выше код метода adjustedSize, который вызывается после enshurePolished. Он отдает некий adjusted (выверенный) размер для виджета. Так вот алгоритм довольно примитивный тут. 

Сначала у виджета запрашивается sizeHint.

Что такое sizeHint... Это виртуальный метод, который есть у каждого виджета и который можно переопределить в наследнике. То есть можно реализовывать любые алгоритмы вычисления подсказки размера виджета в разных ситуациях.

После sizeHint проверяются некоторые ограничения: если включена корректировка высоты по ширине этот размер соответственно корректируется. Потом если у виджета включены expanding (растягивания) по соответствующим направлениям он растягивается, но минимальный размер виджета фиксируется  в размере 200*100 (наверное пикселей). И потом проверяется, что размер будет не больше 2/3 экрана дисплея.

resize вызывается последним в методе adjustSize для установки новых размеров виджету:


void QWidget::resize(const QSize &s)
{
    Q_D(QWidget);
    setAttribute(Qt::WA_Resized);
    if (testAttribute(Qt::WA_WState_Created)) {
        d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
        d->setDirtyOpaqueRegion();
    } else {
        data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
        setAttribute(Qt::WA_PendingResizeEvent);
    }
}

Также будет полезно ознакомиться с updateGeometry()