Рис. 6.1. Окно диалога Find File.
Абсолютное позиционирование является самым негибким способом компоновки виджетов. Он предусматривает жесткое кодирование в программе размеров и позиций дочерних виджетов формы и фиксированный размер самой формы. Ниже показано, какой вид принимает конструктор FindFileDialog при применении абсолютного позиционирования:
01 FindFileDialog::FindFileDialog(QWidget *parent)
02 : QDialog(parent)
03 {
04 namedLabel->setGeometry(9, 9, 50, 25);
05 namedLineEdit->setGeometry(65, 9, 200, 25);
06 lookInLabel->setGeometry(9, 40, 50, 25);
07 lookInLineEdit->setGeometry(65, 40, 200, 25);
08 subfoldersCheckBox->setGeometry(9, 71, 256, 23);
09 tableWidget->setGeometry(9, 100, 256, 100);
10 messageLabel->setGeometry(9, 206, 256, 25);
11 findButton->setGeometry(271, 9, 85, 32);
12 stopButton->setGeometry(271, 47, 85, 32);
13 closeButton->setGeometry(271, 84, 85, 32);
14 helpButton->setGeometry(271, 199, 85, 32);
15 setWindowTitle(tr("Find Files or Folders"));
16 setFixedSize(365, 240);
17 }
Абсолютное позиционирование имеет много недостатков:
• пользователь не может изменить размер окна;
• некоторый текст может оказаться отсеченным, если пользователь выбирает необычно большой шрифт или если приложение переводится на другой язык;
• виджеты могут иметь неправильные размеры для некоторых стилей;
• расчет позиций и размеров должен производиться вручную. Этот процесс утомителен и приводит к ошибкам; кроме того, это сильно затрудняет сопровождение.
В качестве альтернативы абсолютному позиционированию используется ручная компоновка. При ручной компоновке виджетам все же придаются абсолютные позиции, но размеры виджетов становятся пропорциональными размеру окна, а не жестко кодируются в программе. Это может достигаться путем переопределения функции формы resizeEvent() для установки геометрических размеров своих дочерних виджетов:
01 FindFileDialog::FindFileDialog(QWidget *parent)
02 : QDialog(parent)
03 {
04 SetMinimumSize(265, 190);
05 resize(365, 240);
06 }
07 void FindFileDialog::resizeEvent(QResizeEvent * /* event */)
08 {
09 int extraWidth = width() - minimumWidth();
10 int extraHeight = height() - minimumHeight();
11 namedLabel->setGeometry(9, 9, 50, 25);
12 namedLineEdit->setGeometry(65, 9, 100 + extraWidth, 25);
13 lookInLabel->setGeometry(9, 40, 50, 25);
14 lookInLineEdit->setGeometry(65, 40, 100 + extraWidth, 25);
15 subfoldersCheckBox->setGeometry(9, 71, 156 + extraWidth, 23);
16 tableWidget->setGeometry(9, 100, 156 + extraWidth, 50 + extraHeight);
17 messageLabel->setGeometry(9, 156 + extraHeight, 156 + extraWidth, 25);
18 findButton->setGeometry(171 + extraWidth, 9, 85, 32);
19 stopButton->setGeometry(171 + extraWidth, 47, 85, 32);
20 closeButton->setGeometry(171 + extraWidth, 84, 85, 32);
21 helpButton->setGeometry(171 + extraWidth, 149 + extraHeight, 85, 32);
22 }
Мы устанавливаем в конструкторе FindFileDialog минимальный размер формы на значение 265 × 190 и ее начальный размер на значение 365 × 240. В обработчике событий resizeEvent() мы отдаем все дополнительное пространство виджетам, размеры которых мы хотим увеличить. Это обеспечивает плавное изменение вида формы при изменении пользователем ее размеров.
Рис. 6.2. Изменение размеров диалогового окна, допускающего изменение своих размеров.
Точно так же, как при абсолютном позиционировании, при ручной компоновке в программе приходится жестко задавать много констант, рассчитываемых программистом. Написание подобной программы представляет собой нудное занятие, особенно если проект изменяется. И все-таки существует риск отсечения текста. Этого риска можно избежать, принимая во внимание идеальные размеры дочерних виджетов, но это еще больше усложняет программу.
Самый удобный метод компоновки виджетов на форме — использование менеджеров компоновки Qt. Менеджеры компоновки обеспечивают осмысленные, принимаемые по умолчанию значения параметров для каждого типа виджета и учитывают идеальный размер каждого виджета, который, в свою очередь, обычно зависит от шрифта виджета, его стиля и содержимого. Менеджеры компоновки также учитывают максимальные и минимальные размеры и автоматически подстраивают компоновку в ответ на изменения шрифта, изменения содержимого и изменения размеров окна.