Сложность концепции компоновки на примере для QT (шпаргалка)

—

от автора

Описания компоновки (управления автоматическим размещением визуальных элементов) которые мне попадались на родном языке мне кажутся не достаточно погружают читателя в реальную проблематику которая стоит за этим процессом. Мне хочется акцентировать внимание на том откуда берется сложность в этом вопросе. Хотелось бы чтобы кто-то покритиковал мои формулировки.


В книжке по QT можно найти вот такой пример управления компоновкой элементов (кнопок например) в окне:

#include <QtWidgets> int main(int argc, char** argv) {     QApplication app(argc, argv);     app.setApplicationDisplayName("Вложенное размещение");     QWidget wgt;      QPushButton* pcmdA = new QPushButton("A");     QPushButton* pcmdB = new QPushButton("B");     QPushButton* pcmdC = new QPushButton("C");     QPushButton* pcmdD = new QPushButton("D");      QVBoxLayout* pvbxLayout = new QVBoxLayout;     QHBoxLayout* phbxLayout = new QHBoxLayout;     phbxLayout->setMargin(5);     phbxLayout->setSpacing(15);     //В горизонтальную компоновку     //добавляем виджеты кнопок pcmdC и pcmdD     phbxLayout->addWidget(pcmdC);     phbxLayout->addWidget(pcmdD);      pvbxLayout->setMargin(5);     pvbxLayout->setSpacing(15);     //Виджеты кнопок pcmdA и pcmdB по очереди передаются     //в метод QLayout::addWidget() вертикальной компоновки pvbxLayout     pvbxLayout->addWidget(pcmdA);     pvbxLayout->addWidget(pcmdB);     //При помощи метода QBoxLayout:: addLayout()      //передается объект горизонтальной компоновки phbxLayout     pvbxLayout->addLayout(phbxLayout);     //Вызов метода QWidget::setLayout() устанавливает     //вертикальную компоновку pvbxLayout в виджете wgt     wgt.setLayout(pvbxLayout);     wgt.show();     return app.exec(); }

Этот код создает вот такое окно  с четырьмя кнопками внутри:

созданное окно

созданное окно

Мы можем видеть что код выглядит очень естественно он фактически отражает процесс рисования объектов на экране.

Если коротко сформулировать что здесь закодировано на человеческом языке

  • Мы создаем окно,

    задаем ему способ вертикальной компоновки,

    добавляем два визуальных объекта (две кнопки),

    и устанавливаем способ горизонтальной компоновки для третьего объекта, который будет составным объектом,

    и в который мы добавим еще два визуальных объекта (кнопки) из которых он будет состоять.

Я поясню идею компоновки как я ее понимаю. QT дает возможность задавать размеры и координаты визуальных элементов (виджетов) внутри контейнера в который они помещены, напрямую вызывая соответствующие методы этих виджетов. Но если вы хотите определить некоторый алгоритм вычисления этих координат и размеров в зависимости от количества виджетов (например) помещенных в один контейнер вы должны будете постоянно выполнять вычисления этих координат и размеров при каждом добавлении виджета в контейнер, но эти параметры нужны только во время отрисовки, то есть когда все контейнеры заполнены и все количества известны. Объект компоновки как раз позволяет отложить эти вычисления координат и размеров до момента перед самым рисованием. Перед тем как отрисовать окно и все дочерние виджеты в нем вызываются функции стандартного интерфейса компоновки, который наследуют все объекты компоновки, чтобы посчитать и задать координаты и размеры всех дочерних элементов в окне. Как мы видим из приведенного примера объекты компоновки также допускают вложенность. В нашем примере объект вертикальной компоновки принимает объект горизонтальной компоновки в качестве дочернего.

Я хочу обратить ваше внимание на некоторую двойственность сущности объекта компоновки в QT. С одной стороны объект компоновки определяет способ размещения своих дочерних виджетов (вертикальный, горизонтальный, можно создать например горизонтальный с переходом на следующую линию как построчный, можно расставлять наискось, …, можно придумать неограниченное количество способов компоновки вообще говоря). Способ размещения виджетов это фактически функция (логика) которую мы определяем и отдаем любому виджету чтобы перед отрисовкой его контента, координаты и размеры элементов этого контента сконфигурировались по определенному алгоритму.

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

Как вы думаете как вместо второй кнопки добавить другую пару визуальных объектов (чек-боксов например) по горизонтали?

мое предположение

надо создать вместо кнопки В еще один объект компоновки и добавить в него чек-боксы и потом добавить этот новый QHBoxLayout как первый объект компоновки перед добавлением того QHBoxLayout который уже есть в коде?

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

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

1. Главное окно (QWidget wgt)

1.1. -Объект вертикальной компоновки (QVBoxLayout* pvbxLayout)

1.1.1. —Кнопка А

1.1.2. —Кнопка B

1.1.3. —Объект горизонтальной компоновки (QVBoxLayout* pvbxLayout)

1.1.3.1. —Кнопка С

1.1.3.2. —Кнопка D

На самом деле такая иерархия не совсем корректна с точки зрения QT так как объекты компоновки не являются наследниками класса QWidget они являются наследниками класса QLayout и поэтому вместо одной иерархии при программировании мы будем иметь дело с двумя горизонтально связанными иерархиями: иерархия виджетов и иерархия QLayout -ов.

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


ссылка на оригинал статьи https://habr.com/ru/articles/877218/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *