Новости программы Industrial Software Engineering
Укажите свой email для того чтобы получать полезные материалы по индустриальной разработке программного обеспечения
Новости программы Industrial Software Engineering
Укажите свой email для того чтобы получать полезные материалы по индустриальной разработке программного обеспечения

Как создавать UI на Qt. Менеджеры компоновки и стандартные диалоги

Управление временем жизни Qt объектов. Менеджеры компоновки (Layouts). Стандартные классы диалогов
Поговорим об управлении временем жизни объектов в Qt, менеджерах компоновки и стандартных классах диалогов.

Прежде всего стоит отметить, что все объекты QObject , которые создаются в Qt, связаны друг с другом отношением "родитель-потомок". Это позволяет не заботиться о том, чтобы управлять временем жизни объектов. Объекты образуют иерархию, которая похожа на то, как устроены процессы в Linux. То есть, есть какой-то процесс верхнего уровня, далее дерево процессов некоторых "потомков". В свою очередь, "потомки"могут быть связаны с другими потомками и так далее. В любом случае, наверху есть ограниченное количество объектов, которые управляют временем жизни других объектов. Например, виджеты могут быть соподчинены друг другу в соотношении "родитель-потомок".

Таким образом, каждый виджет или объект QObject верхнего уровня вместе со своими подобъектами (потомками) составляет дерево. Каждый QObject содержит в конструкторе указатель на родительский объект. Когда удаляется родительский объект, то удаляются и потомки. Если в качестве родителя указывается NULL, то объект не имеет родителя и будет удален при завершении приложения. Особую роль отношения "родитель-потомок" играют тогда, когда мы начинаем строить сцену с виджетами. Дело в том, что QWidget является базовым классом для всех виджетов, он расширяет семантику отношения родитель-потомок. Если мы устанавливаем родителя для какого-то виджета, то виджет становится соподчиненным виджетом, то есть приобретает систему координат в системе координат родителя, и обрезается по границе родителя. Мы не можем установить размеры виджета-потомка больше, чем размеры родителя, потому что это будет обрезано автоматически системой, которая отрисовывает виджеты. При использовании менеджера компоновки или layout manager, потомки встраиваются в этот менеджер компоновки, согласно тому правилу, которую предлагает менеджер компоновки.

Что нужно знать о виджетах?

  • Все виджеты являются потомками QWidget - это родительский класс для всех виджетов в системе.
  • Каждый конструктор виджета обязательно содержит указатель на родительский вид. Содержит Window Flag, который определяет каким образом этот виджет представляется в интерфейсе пользователя.
  • Виджеты верхнего уровня обязаны иметь родителя равного NULL.
  • Все вложенные виджеты (потомки) обязаны иметь конкретного родителя. Если не указать конкретного родитель, то интерфейс пользователя "развалится" и станет неуправляемым.

Отношение родитель-потомок реализовано с помощью стандартного шаблона проектирования, который называется composition. Это значит, что каждый объект QObject и его наследники содержит список потомков, то есть является контейнером ссылок или указателей на такие же объекты, как и он сам. Если посмотреть на слайд, то можно увидеть, что есть группа функций, которая полезна для перечисленмя объектов, их получения, получения ссылки на родителя, переподчинения группы объектов другому родителя, получения списка потомков, переподчинения виджетов не создавая объекты заново. Когда вы используете динамический интерфейс пользователя, это может оказаться очень удобным.

Давайте рассмотрим пример. На слайде вы видите пример диалогового окна с конструкцией. Родительский виджет может быть , например, QWidget. Внутри него есть один потомок, который называется appointment details он группирует набор элементов - это QGroupBox. Внутри QGroupBox есть разные виджеты - метки, виджет выбора даты, виджет выбора времени, виджет ввода текста. Эти виджеты являются потомками QGroupBox.

Теперь поговорим о менеджерах компоновки. Самый простой способ размещения элементов на виджете - это указание его координат и размеров. Однако, несмотря на свою простоту, этот метод очень не эффективен, так как пользователь меняет размеры диалогового окна, а значит нужно каждый раз пересчитывать координаты, отлавливать события и размещать заново виджеты на форме. Существует специальный класс объектов, которые называются layout manager или менеджер компоновок. Есть набор правил, который позволяет размещать виджеты визуальные в визуальном контейнере. Если посмотреть на слайд, то можно увидеть, что здесь есть четыре базовых менеджера компоновки, которые доступны из коробки.То есть, это QHBoxLayout - горизонтальная линия, QGridLayout - матрица или сетка, QFormLayout - форма ввода, где слева- лейблы, а справа - поля, QVBoxLayout - вертикальная линия.

Добавление элементов в Layout рассмотрим позже. Это делается с помощью метода AddWidget, но важно знать, что не ограничивается набором Layout, мы можем делать некоторые композиции. Например, взять горизонтальный Layout, вставить туда несколько вертикальных, вставить форму и тд. Таким образом, мы можем создать расположение элементов любой сложности. Добавление Layout внутрь другого Layout делается с помощью функции runtime.
  • QWidget - родитель для всех GUI классов, включая элементы интерфейса - кнопки, меню, чекбоксы, поле ввода…
  • QMainWindow - базовый класс для всех приложений с классическим окном, содержащим меню, тулбоксы, строку статуса..
  • QDialog - окно диалога. Диалог после завершения имеет результат (данные от пользователя)
Как использовать QDialog? Прежде всего, нужно сказать, что есть модальные и немодальные диалоги.

Модальный диалог - это диалог, который перехватывает фокус на себя и работает с пользователем, не давая ему выйти в другие поля. Его ввод сосредоточен в диалоге до тех пор, пока он его не закрывает .

Немодальный диалог- это диалог, который не перехватывает фокус, находится рядом, пользователь может обращаться к другим элементам интерфейса пользователя и что-либо делать. После завершения диалога, как правило, есть некоторое значение, которое может возвращаться в программу. Есть много стандартных классов диалога, которые поддерживают вид того окружения, в котором работает пользователь. Например, если вы используете какой-нибудь диалог для выбора цвета, например QColorDialog в Linux, он будет выглядеть также как и обычно в любом приложении. Посмотрим на интерфейс некоторых классов диалогов, которые доступны из коробки и удобно использовать в программах.

QFileDialog - хорошо и удобно настраиваемый диалог для выбора и создания файлов, переименования файлов, создание папок. Многое зависит от возможностей стандартных диалогов конкретной операционной системы, где вы запускаете ваш код. Все, что вы можете представить в вашей операционной системе, QFileDialog - все это может реализовать.

В нем есть несколько переменных, которые вам могут пригодиться, когда вы будете пользоваться:
  1. acceptMode - как диалог принимает от пользователя ввод - каталог, один файл или группа файлов.
  2. defaultSuffix - это то, что на рисунке называется файлтайп - некоторая маска, которая позволяет выбрать файлы конкретного типа.
  3. fileMode - дополнительный режим доступа к файлам, которые мы можем использовать

QInputDialog - набор очень простых элементов, которые размещены на диалоге, некий элемент ввода, (например, число, строчка, бокс, чекбокс) который снабжен кнопками Cancel и Ok. Таким образом, вы можете задавать очень простые вопросы пользователю, не разрабатывая никакого своего интерфейса. вы можете просто запустить этот диалог и настроить его и получаете значение. Обратите внимание, что вы можете получить значение определенного типа, в зависимости от типа элемента, который размещен на этом диалоге.

QMessageBox и QErrorMessage - это стандартные диалоги для оповещения пользователя. QMessageBox - необходим для сообщения пользователю какой-то информации без ожидания ввода от пользователя. У QMessageBox есть несколько различных типов - вопрос, утверждение, предупреждение. QErrorMessage - сообщение пользователю об ошибке.

QColorDialog - стандартный или расширенный колорпикер, который позволяет системе выбрать цвет не только на поле выбора цвета, но и на десктопе. Например, если вы хотите выбрать другой цвет на другом окне, то есть реализации, которые позволяют нажать на необходимый цвет. Этот цвет будет установлен.

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

QPrintDialog - позволяет работать с принтером.

Для того, чтобы разобраться как работает layoutmanager создадим новый проект, выберем QWidget application, назовем его layout , базовым классом сделаем просто виджет, форму не генерируем. Есть заготовленный pro-файл, есть main ,который создает некоторый объект класса виджет. Класс виджет - это наследник QWidget, его реализация тривиальная. При запуске этого проекта - получаем белый прямоугольник, который может закрываться. То есть, нажатие на кнопку, приводит к закрытию окна. Добавим QVBoxLayout и кнопку. Кстати F4 - позволяет быстро переключаться между объявлением класса и определением.

Инициализируем Layout. Есть конструктор, который принимает строчку. Назначаем "Push, me" и родителя this. Назначаем Layout виджету. Также можно указать наш виджет в качестве родителя при создании этого Layout. Добавляем m_button. Попробуем собрать приложение. Запускаем и получаем виджет с кнопкой, на которую можно нажимать.

Давайте добавим дополнительных элементов пользователю, например, текст и поле ввода. Для начала их надо объявить в качестве переменных в нашем классе и создать эти объекты. Нам потребуется еще один Layout - горизонтальный. Заводим переменную для нового Layout - это тот Layout, который будет содержать лейбл и поле ввода. Для его создания мы берем исходный родительский Layout. Обратите внимание, что виджеты добавляются с помощью addWidget, а Layout с помощью addItem. Теперь необходимо создать эти элементы. Собираем и запускаем. В результате появилось окно в котором мы видим вертикальный Layout, который делит пространство нашего виджета пополам. Внутри этого Layout есть два элемента - верхний горизонтальный и нижний, содержащий кнопку. Внутри верхнего Layout есть два элемента - Имя и поле ввода.