Описания компоновки (управления автоматическим размещением визуальных элементов) которые мне попадались на родном языке мне кажутся не достаточно погружают читателя в реальную проблематику которая стоит за этим процессом. Мне хочется акцентировать внимание на том откуда берется сложность в этом вопросе. Хотелось бы чтобы кто-то покритиковал мои формулировки.
В книжке по 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/
Добавить комментарий