Следующий пример показывает -- как организовать реакцию приложения на действия пользователя. Это приложение содержит кнопку, при нажатии на которую программа закрывается. Исходный текст очень похож на предыдущий пример, за исключением того, что теперь, в качестве главного виджета, вместо QLabel используется QPushButton, и добавлен код, который обслуживает факт ее нажатия.
Рисунок 1.3. Приложение Quit.
1 #include <qapplication.h>
2 #include <qpushbutton.h>
3 int main(int argc, char *argv[])
4 {
5 QApplication app(argc, argv);
6 QPushButton *button = new QPushButton("Quit", 0);
7 QObject::connect(button, SIGNAL(clicked()),
8 &app, SLOT(quit()));
9 app.setMainWidget(button);
10 button->show();
11 return app.exec();
12 }
Виджеты Qt имеют возможность посылать приложению сигналы, извещая его о том,
что пользователь произвел какое-либо действие или о том, что виджет
изменил свое состояние [1] .
Например, экземпляры класса QPushButton посылают приложению сигнал
clicked(), когда пользователь
нажимает на кнопку. Сигнал может быть "подключен" к
функции-обработчику (такие функции-обработчики в Qt называются
слотами). Таким образом, когда виджет
посылает сигнал, автоматически вызывается слот. В нашем
примере мы подключили сигнал clicked(), от кнопки, к слоту quit(), экземпляра класса QApplication. Вызовы SIGNAL() и SLOT() -- это макроопределения, более
подробно мы остановимся на них в следующей главе.Теперь соберем приложение. Надеемся, что вы уже создали каталог quit и разместили в нем файл quit.cpp. Дайте команду qmake, для создания файла проекта, а затем второй раз -- для создания Makefile:
qmake -project
qmake quit.pro
Теперь соберите приложение командой make и запустите его. Если вы
щелкнете по кнопке "Quit" или нажмете на клавиатуре клавишу
"Пробел", то приложение завершит свою работу.В следующем примере мы покажем как можно использовать сигналы и слоты для синхронизации двух виджетов. Эта программа предлагает пользователю ввести свой возраст. Сделать это можно либо с помощью кнопок управления счетчиком, либо с помощью ползунка.
Рисунок 1.4. Приложение Age.
Приложение содержит три виджета: QSpinBox, QSlider и QHBox (область горизонтальной разметки). Главным виджетом приложения назначен QHBox. Компоненты QSpinBox и QSlider помещены внутрь QHBox и являются подчиненными, по отношению к нему.
Рисунок 1.5. Виджеты приложения Age.
1 #include <qapplication.h>
2 #include <qhbox.h>
3 #include <qslider.h>
4 #include <qspinbox.h>
5 int main(int argc, char *argv[])
6 {
7 QApplication app(argc, argv);
8 QHBox *hbox = new QHBox(0);
9 hbox->setCaption("Enter Your Age");
10 hbox->setMargin(6);
11 hbox->setSpacing(6);
12 QSpinBox *spinBox = new QSpinBox(hbox);
13 QSlider *slider = new QSlider(Qt::Horizontal, hbox);
14 spinBox->setRange(0, 130);
15 slider->setRange(0, 130);
16 QObject::connect(spinBox, SIGNAL(valueChanged(int)),
17 slider, SLOT(setValue(int)));
18 QObject::connect(slider, SIGNAL(valueChanged(int)),
19 spinBox, SLOT(setValue(int)));
20 spinBox->setValue(35);
21 app.setMainWidget(hbox);
22 hbox->show();
23 return app.exec();
24 }
В строках с 8 по 11 создается и настраивается QHBox. [2] Чтобы
вывести текст в заголовке окна, вызывается setCaption(). А затем устанавливается размер
пустого пространства (6 пикселей) вокруг и между подчиненными
виджетами.В строках 12 и 13 создаются QSpinBox и QSlider, которым, в качестве владельца, назначается QHBox.
Не смотря на то, что мы явно не задали ни положение, ни размеры виджетов QSpinBox и QSlider, тем менее они очень аккуратно расположились внутри QHBox. Собственно для этого и предназначен QHBox. Он выполняет автоматическое размещение подчиненных виджетов, назначая им координаты размещения и размеры, в зависимости от их требований и собственных настроек. В Qt имеется много классов, подобных QHBox, которые избавляют нас от рутинной работы по ручной подгонке положения и размеров визуальных компонентов.
В строках 14 и 15 устанавливаются допустимые пределы изменения счетчика и ползунка. (Мы можем смело предположить, что возраст нашего пользователя едва ли превысит 130 лет.) Два вызова connect(), в строках с 16 по 19 синхронизируют ползунок и счетчик, благодаря чему они всегда будут отображать одно и то же значение. Всякий раз, когда значение одного из виджетов изменяется, он посылает сигнал valueChanged( int ), который поступает в слот setValue( int ) другого виджета.
В строке 20 устанавливается первоначальное значение (35) счетчика. Когда это происходит, счетчик посылает сигнал valueChanged(int), со значением входного аргумента, равным 35. Это число передается в слот setValue(int) виджета QSlider, который устанавливает значение этого виджета равным 35. После этого уже QSlider посылает сигнал valueChanged(int), поскольку его значение только что изменилось, вызывая таким образом слот setValue(int) виджета QSpinBox. Но на этот раз счетчик не посылает сигнал, поскольку его значение и так было равно 35. Таким образом предотвращается бесконечная рекурсия. Рисунок 1.6 иллюстрирует эту ситуацию.
Рисунок 1.6. Изменение одного значения вызывает изменение другого.
В строке 22 QHBox делается видимым (вместе со всеми подчиненными виджетами).
Подход к формированию интерфейса в Qt очень прост для понимания и чрезвычайно гибок. В общем случае, программист выбирает необходимые ему виджеты, размещает их внутри областей выравнивания (layouts), которые в свою очередь принимают на себя обязанности по размещению виджетов, и настраивает свойства виджетов. На заключительном этапе устанавливаются взаимосвязи виджетов, через механизм сигналов и слотов, которые обусловливают поведение пользовательского интерфейса.
[1] |
Сигналы, в терминологии Qt -- совершенно не то же самое, что в терминологии Unix. На протяжении всей книги мы будем говорить исключительно о Qt-сигналах. |
[2] |
Если во время компиляции возникла ошибка в строке 8, то это означает, что у вас установлена более старая версия Qt, чем требуется. Напоминаем еще раз, что для прогона примеров из этой книги вы должны установить Qt 3.2 или более поздний выпуск Qt 3. |
Пред. | В начало | След. |
Начало. | На уровень выше | Работа со справочной системой. |