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

Изучение 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-репозитории. Насчет немного я, конечно, пошутил :) В этой части предстоит больше

Может ли TreeSet содержать дубликаты?

Не спешите давать ответ, а лучше запустите код, приведенный ниже. Возможно вы подумаете, что это надуманный пример, но это лишь немного упрощенная версия того кода, с которым мне пришлось столкнуться на практике. Для начала о проблеме, которую был призван решить этот код. В списке объектов надо было оставить объекты с различными именами, причем неважно какой объект из всего набора с таким же именем останется. Сразу же уточню, что на практике в проекте используется Java 7 и класс объектов, добавляемых в TreeSet, не вложен в какой-либо другой, а приведенный здесь вариант использован для краткости. Может возникнуть вопрос почему выбрано именно такое решение. Давайте разберемся, чтобы не повторять ошибку. Первое, что приходит в голову, когда из списка надо удалить дубликаты, - использовать Set. В данной ситуации HashSet не подходит, потому что он использует equals метод для сравнения и отсеивания дубликатов. Но наш программист не сдаётся и вспоминает, что есть же еще TreeSet, в докум

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

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