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

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

13.2 Компоновка (Layouts)

Для того, чтобы оптимально разместить виджеты на форме, необходимо учесть ряд деталей:

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

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

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

Компоновщик не принадлежит к виджетам, не наследует от QWidget и является невидимым на форме. Он только управляет её размером и размещением её содержания.

Обычно используют три основных класса компоновщика:

  • вертикальная компоновка (класс QVBoxLayout);
  • горизонтальная компоновка (класс QHBoxLayout);
  • компоновка сеткой (класс QGridLayout);

Для того, чтобы продемонстрировать работу с компоновками, используем предыдущий пример добавив ещё несколько элементов и сделав так, чтобы размещение элементов было пропорциональным и соответствовало изменениям размеров окна. Попытаемся создать такой интерфейс:

  • метки и поля ввода разместим горизонтально в одной строке;
  • создадим три такие строки с метками и полями;
  • добавим ещё одну строку с двумя кнопками горизонтально и правым выравниванием.

Создадим проект LayoutExample. Для этого воспользуемся мастером новых проектов. Выберем в списке Qt Widgets Application. Зададим название для проекта и настроим класс главного окна: зададим родительский класс (в выпадающем списке Base Class установим QWidget) и снимем флажок для автоматической генерации файла формы (Generate Form) (см. рис. 13.4).

Создание класса окна

увеличить изображение
Рис. 13.4. Создание класса окна

Откроем файл mainwindow.cpp и изменим код конструктора окна:

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
MainWindow::MainWindow ( QWidget * parent ) : QWidget ( parent )
{
	//Первая горизонтальная строка. Начальный текст в поле ввода
	QLineEdit * lLineEdit = new QLineEdit ( " Text1 " );
	//Задаём текст. & — означает комбинацию клавиш для активации виджета
	QLabel * lLabel = new QLabel ( " LineEdit &1 " );
	//Задаём виджет на который будет переключаться фокус ввода при нажатии Alt+1
	lLabel ->setBuddy ( lLineEdit );
	//Размещаем поле ввода и метку в одной строке
	QHBoxLayout *lHBoxLayout = new QHBoxLayout;
	lHBoxLayout->addWidget ( lLabel );
	lHBoxLayout->addWidget ( lLineEdit );
	//Вторая горизонтальная строка
	QLineEdit * lLineEdit 2 = new QLineEdit ( " Text2 " );
	QLabel * lLabel 2 = new QLabel ( " LineEdit &2 " );
	lLabel 2 ->setBuddy ( lLineEdit 2 );
	QHBoxLayout *lHBoxLayout2 = new QHBoxLayout;
	lHBoxLayout2->addWidget ( lLabel 2 );
	lHBoxLayout2->addWidget ( lLineEdit 2 );
	//Третий ряд виджетов с кнопками
	QPushButton *lPushButtonOk = new QPushButton ( " & ok " );
	QPushButton * lPushButtonCancel=new QPushButton ( " & Cancel " );
	QHBoxLayout *lHBoxLayout3 = new QHBoxLayout;
	//Добавим элемент-растяжку он займёт всё возможное свободное пространство
	//и "прижмёт"кнопки к краю
	lHBoxLayout3->addStretch ( );
	lHBoxLayout3->addWidget ( lPushButtonOk );
	lHBoxLayout3->addWidget ( lPushButtonCancel );
	//Добавим компоновку вертикально в колонку
	QVBoxLayout *lVBoxLayout = new QVBoxLayout;
	lVBoxLayout->addLayout ( lHBoxLayout );
	lVBoxLayout->addLayout ( lHBoxLayout2 );
	lVBoxLayout->addLayout ( lHBoxLayout3 );
	//Задаём компоновщик для окна
	setLayout ( lVBoxLayout );
}

После запуска программы получим главное окно с размещёнными в компоновщиках виджетами (см. рис. 13.5).

Пример: компоновка виджетов

Рис. 13.5. Пример: компоновка виджетов

13.2.1 Компоновка сеткой (класс QGridLayout)

Рассмотрим работу с компоновщиками на ещё одном примере. На этот раз мы создадим простую программу-калькулятор и используем компоновщики QGridLayout.

Создадим новый проект так же, как для предыдущего примера. Добавим члены класса — указатели на цифровые кнопки (0-9), кнопку для сброса результата (С) и для суммирования\отображения результата (+/ =). Для создания визуальных элементов в окне — объявим отдельный частный метод createWidgets().

#include <QWidget>
//Предварительное объявление классов
class QPushButton;
class QLCDNumber;
class CalculatorMainWindow : public QWidget
{
	Q_OBJECT
public :
	explicit CalculatorMainWindow ( QWidget * parent = 0 );
	˜CalculatorMainWindow ( );
private :
	//Отдельный метод для создания интерфейса программы
	void createwidgets ( );
private :
	//Цифровые кнопки
	QPushButton *pushButton;
	QPushButton *pushButton_2;
	QPushButton *pushButton_3;
	QPushButton *pushButton_4;
	QPushButton *pushButton_5;
	QPushButton *pushButton_6;
	QPushButton *pushButton_7;
	QPushButton *pushButton_8;
	QPushButton *pushButton_9;
	QPushButton *pushButton_10;
	//Кнопка вывода результата и суммирования
	QPushButton *pushButtonP lus;
	//Кнопка сброса результата
	QPushButton *pushButtonC;
	//Виджет — цифровой дисплей
	QLCDNumber *lcdNumber;
};

В файл реализации включим необходимые .h-файлы:

#include <QPushButton>
#include <QGridLayout>
#include <QLCDNumber>

Определим метод createWidgets(), ответственный за создание интерфейса программы-калькулятора. В нём создадим элемент QLCDNumber для отображения следующего слагаемого и результата. Для упрощения примера запрограммируем только операцию сложения целых чисел. Поэтому калькулятор будет содержать только цифровые кнопки (0-9), кнопку добавления/вывода результата и кнопку сброса результата. Все элементы пользовательского интерфейса разместим в одной компоновке QGridLayout:

void CalculatorMainWindow::createwidgets ( )
{
	QGridLayout *lCalcLayout = new QGridLayout;
	setLayout ( lCalcLayout );
	lcdNumber = new QLCDNumber;
	pushButton = new QPushButton ( " 1 " );
	pushButton_2 = new QPushButton ( " 2 " );
	pushButton_3 = new QPushButton ( " 3 " );
	pushButton_4 = new QPushButton ( " 4 " );
	pushButton_5 = new QPushButton ( " 5 " );
	pushButton_6 = new QPushButton ( " 6 " );
	pushButton_7 = new QPushButton ( " 7 " );
	pushButton_8 = new QPushButton ( " 8 " );
	pushButton_9 = new QPushButton ( " 9 " );
	pushButton_10 = new QPushButton ( " 0 " );
	pushButtonC = new QPushButton ( " C " );
	pushButtonP lus = new QPushButton ( " + / = " );
	lCalcLayout->addWidget ( lcdNumber, 0, 0, 1, 4 );
	lCalcLayout->addWidget ( pushButton, 1, 0 );
	lCalcLayout->addWidget ( pushButton_2, 1, 1 );
	lCalcLayout->addWidget ( pushButton_3, 1, 2 );
	lCalcLayout->addWidget ( pushButton_4, 2, 0 );
	lCalcLayout->addWidget ( pushButton_5, 2, 1 );
	lCalcLayout->addWidget ( pushButton_6, 2, 2 );
	lCalcLayout->addWidget ( pushButton_7, 3, 0 );
	lCalcLayout->addWidget ( pushButton_8, 3, 1 );
	lCalcLayout->addWidget ( pushButton_9, 3, 2 );
	lCalcLayout->addWidget ( pushButton_10, 4, 0, 1, 3 );
	lCalcLayout->addWidget ( pushButtonC, 1, 3 );
	lCalcLayout->addWidget ( pushButtonP lus, 2, 3, 3, 1 );
}

Метод addWidget() класса QGridLayout принимает в качестве параметров указатель на виджет, а также строку и столбец для размещения виджета. Количество строк и столбцов задают заранее, оно может быть произвольным и определяется в процессе добавления виджетов к компоновщику. Перегруженный вариант метода addWidget() используем для добавления кнопок "0", "+/ =" и виджета QLCDNumber на форму. Он принимает два дополнительных параметра. Они определяют количество ячеек по горизонтали и по вертикали, которые будет занимать виджет в компоновщике. Обычно каждый элемент занимает одну ячейку в компоновщике. Последний параметр метода addWidget() указывает выравнивание элемента внутри ячейки (флажки Qt::Alligment).

В заключение добавим к конструктору вызов метода для создания элементов в окне.

CalculatorMainWindow::CalculatorMainWindow ( QWidget * parent ) : QWidget ( parent )
{
	resize ( 300, 300 );
	setWindowTitle ( " Simple Calculator " );
	createwidgets ( );
}
Сергей Радыгин
Сергей Радыгин

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

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

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

 

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

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