Компания ALT Linux
Опубликован: 07.03.2015 | Доступ: свободный | Студентов: 2134 / 486 | Длительность: 24:14:00
Лекция 13:

Создание графического интерфейса средствами Qt

Аннотация: Изучаются выджеты - визуальные элементы, из которых состоит графический интерфейс пользователя, их компоновка, политика размеров, сигнально-слотовые соединения, элементы графического интерфейса и их использование.

13.1 Виджеты (Widgets)

Виджеты (Widgets) — это визуальные элементы, из которых состоит графический интерфейс пользователя.

Примеры виджетов:

  • Кнопка (класс QPushButton);
  • Метка (класс QLabel);
  • Поле ввода (класс QLineEdit);
  • Числовое поле-счётчик (класс QSpinBox);
  • Строка прокрутки (класс QScrollBar).

В Qt есть около 50-ти готовых классов графических элементов доступных для использования. Родительским классом для всех виджетов является класс QWidget. От него наследуются все главные свойства визуальных элементов, которые мы тщательно рассмотрим. Исследование способов разработки программ с графическим интерфейсом начнём с примера.

Создадим пустой файл проекта. Запустим мастера проектов и выберем в разделе Projects (Проекты) пункт Other Project (Другой проект). Далее выберем тип проекта Empty Qt Project (Пустой проект Qt). К файлу проекта добавим содержимое:

TEMPLATE = app
#Модули Qt, которые мы будем использовать
QT += widgets #Добавляем модуль widgets для работы с виджетами (необходимо для Qt5).
TARGET = widget#Название исполняемого файла
SOURCES += \
main.cpp

Теперь создадим простую программу с окном, в котором мы будем выводить надпись. Установим размер окна и текст его заголовка, а также установим шрифт для надписи. Для этого создадим файл main.cpp со следующим содержанием:

#include <QApplication>
#include <QLabel>
int main ( int lArgc, char * lArgv [ ] )
{
//Создаём объект QApplication, который инициализирует и настраивает оконную программу,
//управляет её выполнением с помощью цикла обработки событий
	QApplication lApplication ( lArgc, lArgv );
	QLabel lLabel; //Создаём виджет QLabel — метка
	lLabel.setText ( " I am widget! " ); //Задаём текст для метки
	lLabel.setGeometry ( 200, 200, 300, 150 );
//Задаём размеры — позицию (x, y) ширину и высоту. Задаём выравнивание текста
	lLabel.setAlignment (Qt::AlignHCenter | Qt::AlignVCenter );
//Класс QFont используют для настройки параметров шрифта.
//Выбираем семейство шрифтов Arial Black и размер 12.
	QFont lBlackFont ( " Arial Black ", 12 );
	lLabel.setFont ( lBlackFont ); //Задаём шрифт для метки
	lLabel.show ( ); //Вызываем метод show() для показа метки на экране.
	return lApplication.exec ( ); //Запускаем программу на выполнение exec() выполняет
//цикл обработки событий. Программа ожидает действия пользователя и выполняет их обработку.
}

Как видим, элементы, из которых состоят интерфейсы в Qt, имеют собственные позицию и размер — так называемую "геометрию" — и, таким образом, занимают соответствующую прямоугольный участок на экране (см. рис. 13.1). Также каждый из элементов имеет настройки, которые определяют его поведение и вид.

Первый оконный проект

Рис. 13.1. Первый оконный проект

Для создания структуры виджеты организовывают в иерархию по принципу "часть — целое". Каждый из виджетов может содержать другие виджеты. Такой визуальный элемент становится "родителем" (родительским виджетом) для элементов, которые он содержит. Отметим, что такие отношения не следует путать с наследованием в C++ — отношениями между классами в программе. Отношения между виджетами являются отношениями между объектами. Такие отношения порождают несколько последствий:

  • родительский элемент будет отвечать за удаление дочернего элемента: если родительский виджет удалят — то он автоматически удалит и все дочерние элементы;
  • родительский виджет размещает дочерние виджеты внутри себя, части дочерних виджетов, которые выходят за пределы родителя будут невидимыми;
  • часть состояния родительского виджета передаётся дочерним — это касается некоторых свойств (видимость, активность) и стилей, которые накладываются на визуальный элемент.

Виджеты, которые не имеют родителя (виджеты верхнего уровня), имеют вид отдельных окон в программе. Рассмотрим пример. Назовём новый проект ParentExample. Файл проекта будет содержать обычные для GUI-проекта настройки:

TEMPLATE = app
TARGET = ParentExample
QT += widgets

Для виджета, который мы будем использовать в качестве главного окна создадим новый класс. Для этого в категории Files and Classes (Файлы и классы) выберем раздел С++ и выберем С++ Class (см. рис. 13.2).

Мастер создания нового класса

увеличить изображение
Рис. 13.2. Мастер создания нового класса

Следующим шагом будет создание нескольких элементов на окне. Для этого откроем файл parentwidget.cpp и изменим код конструктора класса. Для отображения элементов достаточно создать их в конструкторе класса и задать ParentWidget как отца для них. Код parentwidget.cpp выглядит так:

#include " parentwidget.h "
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>
ParentWidget::ParentWidget ( QWidget * parent ) :
QWidget ( parent )
{
//Создаём метку, указывая родительский виджет — this, то есть экземпляр класса ParentWidget.
QLabel * lLabel=new QLabel ( this );
//Позиция относительно левого верхнего угла родительского виджета.
lLabel ->setGeometry ( 50, 0, 100, 30 );
lLabel ->setText ( " TextLabel " ); //Текст на метке.
//Создаём кнопку, задаём "родителя", геометрию и текст
QPushButton * lPushButton = new QPushButton ( this );
lPushButton->setGeometry ( 50, 50, 100, 30 );
lPushButton->setText ( " PushButton " );
//Создаём поле ввода, задаём "родителя", геометрию и текст
QLineEdit * lLineEdit = new QLineEdit ( this );
lLineEdit ->setGeometry ( 50, 100, 100, 30 );
lLineEdit ->setText ( " LineEdit " );
lLineEdit ->selectAll ( ); //Выделяем текст в поле ввода (просто для примера)
//Наконец изменяем размер родительского виджета
setGeometry ( x ( ), y ( ), 300, 150 );
//и задаём текст заголовка окна
setWindowTitle ( " parent widgetExample " );
}

Поскольку родительским элементом является ParentWidget, то метка (QLabel), кнопка (QPushButton) и текстовое поле (QLineEdit) находятся в его пределах. Позицию дочерних виджетов задают относительно левого верхнего угла отца. В этом легко убедиться изменив размеры и позицию окна нашей программы. Обратите внимание на то, как мы создавали элементы пользовательского интерфейса в динамической памяти используя оператор new. Это гарантирует, что элементы не будут удалены после завершения работы конструктора ParentWidget.

Далее добавим в проект файл main.cpp. Наш класс наследует от класса QWidget — базового класса для всех визуальных элементов пользовательского интерфейса, а следовательно будет обладать всеми его особенностями. Создадим экземпляр нашего класса и вызовем метод show() для того, чтобы показать его (см. рис. 13.3).

#include <QApplication>
//Подключаем .h файл с определением нашего класса ParentWidget
#include " parentwidget.h "
int main ( int lArgc, char * lArgv [ ] )
{
	QApplication lApplication ( lArgc, lArgv );
	//Создаём и показываем окно программы
	ParentWidget lParentWidget;
	//Переместить окно в точку экрана с координатами 100, 200
	lParentWidget.move ( 100, 200 );
	lParentWidget.show ( );
	return lApplication.exec ( );
}
Пример создания дочерних виджетов

Рис. 13.3. Пример создания дочерних виджетов
Сергей Радыгин
Сергей Радыгин

Символы кириллицы выводит некорректно. Как сделать чтобы выводился читабельный текст на русском языке?

Тип приложения - не Qt,

Qt Creator 4.5.0 основан на Qt 5.10.0. Win7.

 

Юрий Герко
Юрий Герко

Кому удалось собрать пример из раздела 13.2 Компоновка (Layouts)? Если создавать проект по изложенному алгоритму, автоматически не создается  файл mainwindow.cpp. Если создавать этот файл вручную и добавлять в проект, сборка не получается - компилятор сообщает об отсутствии класса MainWindow. Как правильно выполнить пример?