К основному контенту

Изучение Qt маленькими порциями. Заставляем приложение что-то делать



Итак, прошлый раз мы разбирали шаблон приложения, сгенерированный QtCreator. На этот раз я обещал, что оно будет делать что-то. Начнём с окна дизайнера QtCreator (перейти к нему можно по двойному щелчку по mainwindow.ui). Давайте рассмотрим различные части окна одну за другой.



Список виджетов - область, в которой показаны все доступные виджеты. Имеется два режима отображения: в виде списка и в виде значков. Я предпочитаю режим значков (показанный на рисунке), но режим отображения списка может быть полезным для начинающих. Сменить режим можно из контекстного меню. Для добавления виджета на форму достаточно перетащить его отсюда в место назначения.
Окно свойств - здесь отображаются настройки для текущего виджета. Попробуйте выделить виджет на форме или саму форму и вы получите полный набор свойств, доступных для настройки.
В иерархии объектов показано как всё связано между собой. Например, все виджеты будут размещены внутри экземпляра QMainWindow (названого MainWindowClass). Если вы используете интерфейс с закладками, вы увидите, что виджеты разместятся внутри их.
Список действий содержит действия - особые классы, позволяющие использовать один и тот же объект для панели инструментов, главного меню и сочетаний клавиш.Это действительно удобно при создании классических десктоп-приложений.
Панель инструментов Дизайнера - просто панель инструментов, размещённая в Дизайнере - инструменте, используемом для редактирования .ui файлов. Здесь вы можете переключатся между рабочими режимами дизайнера (редактирование, связи, друзья, порядок обхода виджетов), а также применять и отменять макеты.

Все эти списки и панели инструментов окружают вашу форму, главное окно, диалоговое окно, или виджет, которые в данный момент вы разрабатываете.


Какая всё же разница между виджетом, диалоговым окном и главным окном? Всё, что вы видите на экране - виджет. Это и кнопки, и метки, и окна верхнего уровня. Что дополнительно есть у диалогового или главного окна? Диалоговое окно может быть модальным, т.е. показать окно и ожидать действия. Главное окно используется для состыковки других окон, размещения главного меню, панели инструментов, статусной строки. Тогда возникает вопрос: когда создавать виджет? Вы можете создать виджет для объединения набора других виджетов и использовать его при создании диалоговых окон, главного окна или других виджетов или можете использовать его в качестве основы для простого окна, не нуждающегося в дополнительных возможностях главного окна.


На данный момент цель - получить приложение, которое что-то делает. Мы разделим эту цель на две меньшие: запустить свой код и соединится с одним из слотов Qt. Для достижения первой цели необходимо добавить действия, которые позволили бы пользователю что-то сделать с приложением. В главном меню формы написано “Type Here”. Дважды щёлкнете по тексту и напишите “File”. После этого в раскрывшемся меню вы сможете добавить пункты. Пусть их будет два: “Exit” и “Hello Qt”. В списке действий появятся действия (по одному на каждый созданный пункт меню). Здесь вы можете назначить сочетания клавиш, изменить текст пункта меню, добавить для него пиктограмму (пиктограммы берутся из ресурсов и поскольку они пока не обсуждались просто пропустите этот шаг).




Для действия actionHello_Qt щёлкните правой кнопкой мышки и выберите Go to slot…. Появится список сигналов. Выберите из этого списка triggered(). Вы будете перенаправлены к файлу mainwindow.cpp к методу on_actionHello_Qt_triggered. Этот метод будет выполнен, когда пользователь инициирует действие.




В слоте мы просто изменим заголовок окна на “Hello Qt!”, используя код, приведённый ниже. А теперь попробуйте собрать ваше приложение и запустить его. При выборе пункта меню “Hello Qt” изменится заголовок окна. Итак, цель достигнута, приложение что-то делает.


void MainWindow::on_actionHello_Qt_triggered()
{
setWindowTitle( tr("Hello Qt!") );
}




Почему мы поместили строку в функцию tr? Это необходимо для поддержки со стороны инструментов интернационализации, которые предоставляет Qt. Мы рассмотрим этот вопрос немного позже, а пока просто запомните, что все строки, которые видит пользователь, должны быть обёрнуты в вызов функции tr.


Сигнал, вызванный действием actionHello_Qt, был автоматически связан с предоставленным слотом. Это может быть удобно в большинстве случаев, но я предпочитаю называть слоты, исходя из того, что они делают, а не в зависимости от того, к чему они присоединены. Это не только улучшает читаемость кода, но и позволяет повторно использовать слот для разных сигналов.
Чтобы это сделать необходимо вручную создать связи и именно это я собираюсь сделать для действия actionExit. Если посмотреть на конструктор, то мы увидим, что все элементы интерфейса доступны через переменную ui. Но перед тем как использовать элементы, доступные из указанной переменной, необходимо вызвать функцию setupUi. Как раз после этого вызова вполне естественно прописать связь, а также инициализировать пользовательский интерфейс.
В нашем случае мы свяжем сигнал triggered() для действия actionExit со слотом close. Это значит, что когда пользователь выполнит это действие, окно закроется, что в свою очередь приведёт к завершению приложения. Поскольку слот для закрытия назван close, а не on_actionExit_triggered, необходимо создать связь вручную. Такое название не только вынуждает создать связь вручную, но и делает использование слота более прозрачным, особенно когда его вызов осуществляется в другом месте кода, как обычной функции-члена.


MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindowClass)
{
ui->setupUi(this);

connect( ui->actionExit, SIGNAL(triggered()), this, SLOT(close()) );
}


На сегодня достаточно. В следующий раз я планирую рассказать более подробно о сигналах и слотах.

Комментарии

Популярные сообщения из этого блога

Одно приложение, несколько баз данных

Рецепт от Spring Boot Некоторое время назад мне довелось писать агрегатор информации, разбросанной по нескольким базам данных с разными схемами. Для реализации был выбран Spring Boot. Ну, потому что модный и судя по примерам существенно упрощает жизнь за счет умной автоконфигурации. В этой статье я опишу, что же необходимо сконфигурировать и как, в случае, если вы отошли от стандартного сценария. Первым делом, необходимо прописать настройки доступа к каждой из баз. Например, вот так: Следующим шагом создадим отдельный класс конфигурации (для удобства), в котором определим dataSources: Обратите внимание, как просто получить настройки с помощью @ConfigurationProperties. Правда, пришлось ввести вспомогательный класс BaseDataSourceProperties — наследник DataSourceProperties, в котором область видимости метода getDriverClassName расширена до public. И осталось совсем немного — сконфигурировать JPA-репозитории. Насчет немного я, конечно, пошутил :) В этой части предстоит больше ...

Обработка изображений с ImageMagick

ImageMagick ( http://www.imagemagick.org ) — набор утилит для создания, редактирования, конвертирования и просмотра растровых изображений. Графический режим необходим только для просмотра. Для остальных действий над изображениями достаточно консоли. То есть налицо два отличия от привычных редакторов растровых изображений (вроде GIMP или Krita): использование набора утилит вместо одной программы для операций над изображениями не требуется GUI. Очевидно, что таким инструментом вряд ли будут пользоваться художники, фотографы или дизайнеры. Чтобы разобраться для кого предназначен этот набор, предлагаю ознакомиться с предоставляемыми возможностями. Что умеет ImageMagick? Чтобы ответить на поставленный вопрос я перечислю входящие в набор утилиты, напишу какой функционал предоставляет каждая из них и, конечно же, приведу примеры использования. identify — информационная утилита, воспользовавшись которой можно узнать формат изображения и множество других его свойств (например, высоту,...

Изучение Qt маленькими порциями. Разбираем ваше первое приложение

Прошлый раз вы установили QtCreator, а затем сгенерировали ваше первое приложение. Всё сработало и у вас теперь есть собственное пустое окно QMainWindow на экране. Всё хорошо, но что же действительно было сделано? Давайте пройдёмся по сгенерированному коду, чтобы стало понятно, что же случилось на самом деле. Приложение состоит из одного класса и функции main, необходимой для запуска. Давайте посмотрим на эту функцию main.cpp #include <QtGui/QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } В этой функции создаётся экземпляр класса QApplication . Каждому приложению Qt нужен один и только один экземпляр класса QApplication. Он представляет собой само приложение и содержит главный цикл обработки событий. Вы можете спросить, что такое цикл обработки событий? Это просто цикл, ожидающий наступления события. Например, нажатие клавишы, перемещение мышки, сетевые пакеты, событ...