C++ — Разработка программы на Qt, управляемая голосом — C++ Qt


Содержание

Создание приложения Qt на C++

Этот урок демонстрирует как использовать Qt Creator для написания маленькой программы Qt, Text Finder. Это упрощённая версия примера QtUiTools Text Finder.

Создание проекта Text Finder

Замечание: Создайте проект с активным режимом Справка чтобы вы могли следовать этим инструкциям во время работы.

    Выберите Файл > Новый файл или проект. > Проект Qt C++ > GUI приложение Qt > Выбрать. .

Откроется диалог Введение и размещение проекта.

  • В поле Имя введите TextFinder.
  • В поле Создать в введите путь к файлам проекта. Например, C:\Qt\examples, и нажмите Вперёд.

    Откроется диалог настроек цели.

    Выберите нужный профиль Qt для сборки вашего проекта и нажмите Далее.

    Замечание: Если у вас установлен только один профиль Qt, этот диалог будет пропущен.

    Откроется диалог Информация о классе.

  • В поле Имя класса введите TextFinder в качестве имени класса.
  • В списке Базовый класс выберите QWidget в качестве типа базового класса.

    Замечание: Поля Заголовочный файл, Файл исходников и Файл формы будут обновлены автоматически в соответствии с выбранным вами именем класса.

    Откроется диалог Управление проектом.

  • Проверьте настройки проекта и нажмите Завершить для создания проекта.
  • Проект TextFinder будет содержать следующие файлы:

    • textfinder.h
    • textfinder.cpp
    • main.cpp
    • textfinder.ui
    • textfinder.pro

    Файлы .h и .cpp содержат необходимые строки кода. Файл .pro полностью завершён.

    Заполнение недостающих кусков

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

    Проектирование пользовательского интерфейса

    1. В режиме Редактор дважды нажмите на файле textfinder.ui в виде Проекты для запуска интегрированного Qt Designer.
    2. Перетащите следующие виджеты на форму:
      • Label (QLabel)
      • Line Edit (QLineEdit)
      • Push Button (QPushButton)

    Замечание: Для быстрого поиска виджетов, используйте строку поиска в боковой панели. Например, для поиска виджета Label, начните печатать слово label.

  • Дважды нажмите на виджет Label и введите текст Keyword.
  • Дважды нажмите на виджет Push Button и введите текст Find.
  • В панели Свойства измените значение свойства objectName на findButton.

    Нажмите Ctrl+A для выбора виджетов и нажмите Скомпоновать по горизонтали (или нажмите Ctrl+H) для применения горизонтальной компоновки (QHBoxLayout).

  • Перетащите виджет Text Edit (QTextEdit) на форму.
  • Выберите область экрана и нажмите Скомпоновать по вертикали (или нажмите Ctr+L) для применения вертикальной компоновки (QVBoxLayout).

    Применение вертикальной и горизонтальной компоновок обеспечивает масштабирование интерфейса приложения при различных разрешениях экрана.

  • Для вызова функции поиска при нажатии пользователем кнопки Find вы будете использовать механизм сигналов и слотов Qt. Сигнал вырабатывается когда происходит определённое событие, а слот — это функция которая вызывается в ответ на определённый сигнал. У виджетов Qt есть предопределённые сигналы и слоты которые вы можете использовать прямо из Qt Designer. Чтобы добавить слот для функции поиска:
    • Нажмите правой кнопкой мыши на кнопке Find для открытия контекстного меню.
    • Выберите Перейти к слоту. > clicked(), и нажмите OK.

    Закрытый слот on_findButton_clicked() будет добавлен в заголовочный файл textfinder.h и закрытая функция TextFinder::on_findButton_clicked() будет добавлена в файл исходных кодов textfinder.cpp.

    Для получения дополнительной информации о проектировании форм с Qt Designer смотрите Руководство по Qt Designer.

    Завершение заголовочного файла

    Файл textfinder.h уже содержит необходимые директивы #include, конструктор, деструктор и объект Ui. Вам потребуется добавить закрытую функцию loadTextFile() для чтения и отображения содержимого входного файла в QTextEdit.

    1. В боковой панели Проекты в режиме Редактор нажмите два раза на файле textfinder.h чтобы открыть его для редактирования.
    2. Добавьте закрытую функцию в секцию private за Ui::TextFinder, как продемонстрировано в следующем фрагменте кода:

    Завершение файла исходных кодов

    Теперь заголовочный файл завершён, перейдём к файлу исходных кодов textfinder.cpp.

    1. В боковой панели Проекты в режиме Редактор нажмите два раза на файле textfinder.cpp чтобы открыть его для редактирования.
    2. Добавьте код для загрузки текстового файла с помощью QFile, чтения его с помощью QTextStream, а затем отображения его в textEdit с помощью setPlainText(). Это продемонстрировано в следующем фрагменте кода:
    3. Для использования QFile и QTextStream добавьте следующие директивы #includes в textfinder.cpp:
    4. В слоте on_findButton_clicked() добавьте код извлечения строки поиска и использования функции find() для поиска строки в текстовом файле. Это продемонстрировано в следующем фрагменте кода:
    5. После того как эти функции завершены, добавьте строку для вызова loadTextFile() в конструкторе, как продемонстрировано в следующем фрагменте кода:

    Слот on_findButton_clicked() будет вызван автоматически в сгенерированном uic ui_textfinder.h этой строчкой кода:

    Создание файла ресурсов

    Вам потребуется файл ресурсов (.qrc) в котором вы сохраните входной текстовый файл. Входным файлом может быть любой файл .txt с абзацем текста. Создайте текстовый файл с именем input.txt и сохраните его в каталоге textfinder.

    Чтобы добавить файл ресурсов:

      Выберите Файл > Новый файл или проект > Qt > Файл ресурсов Qt > Выбрать. .

    Откроется диалог Выбор размещения.

  • В поле Имя введите textfinder.
  • В поле Путь введите C:\Qt\examples\TextFinder и нажмите Далее.

    Откроется диалог Управление проектом.

  • В поле Добавить в проект выберите TextFinder.pro и нажмите Завершить для открытия файла в редакторе кода.
  • Выберите Добавить > Добавить префикс.
  • В поле Префикс замените префикс по умолчанию на (/).
  • Выберите Добавить > Добавить файлы для поиска и добавления input.txt.

    Сборка и запуск вашего приложения

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

    Разработка игры на С++, Qt

    Написал ремейк небольшой логической игрушки — «Полный квадрат». Код показался мне достаточно интересным чтобы описать на блоге.

    По сюжету игры, ёжик перемещается по лабиринту из облаков. Ходить ёж умеет только по вертикали и горизонтали, а начав движение идет до тех пор, пока не упрется в пустоту (пройденные облака исчезают), край экрана или грозовую тучу. Необходимо выбрать начальную позицию для ежа и такой маршрут движения, чтобы все облака оказались пройдены.

    В любой игре, чуть более интересной чем «Сапер«, используются анимации, проигрывается звук, поэтому следующие компоненты Qt затронуты в статье:

    • класс QMovie для отображения gif-анимации тучек и ежа;
    • класс QPropertyAnimation — ежик перемещается плавно, при этом меняются его координаты (свойства);
    • QMediaPlayer из модуля Qt Multimedia. При перемещении наш ёжик топает;
    • Qt Style Sheets (QSS) используется для украшения элементов управления.

    снимки игровых экранов

    Содержание:

    Архитектура игры

    Игра состоит из нескольких экранов, которыми управляет ScreenController. Экраны я рисовал с использованием Qt Designer [1]. Каждый игровой экран содержит кнопки, позволяющие перейти на другой экран, события от которых передаются контроллеру.

    Логика игры вынесена в класс GameWidget, который загружает на графическую сцену блоки и как-то обрабатывает их сигналы. Например, если на сцене уже размещен ёжик и пользователь кликнул облачко, то GameWidget обеспечивает перемещение ежа в новую позицию при условии, что это не будет противоречить правилам игры.

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

    WinScreen выводит информацию о победе и предлагает сыграть в игру еще раз.

    Qt Style Sheets (QSS)

    При рисовании интерфейса в Qt Designer использованы самые обычные кнопки текстовые поля. Скругленные углы кнопок, цвет и размер рамки, изменение цвета при наведении и нажатии мыши получены за счет использования таблиц стилей Qt.

    Установить таблицу стилей виджету (QWidget) или приложению (QApplication) можно методом setStyleSheet(). Для стилизации уже готового приложения можно передать таблицу стилей при запуске вместе с соответствующей опцией (-stylesheet style.qss). Таблица стилей Qt являются надстройкой над каскадными таблицами стилей, используемыми при верстке веб страниц (CSS3) [2].

    Ключевым понятием в QSS является селектор, т.е. элемент, к которому мы хотим применить стили, при этом, если некоторому объекту устанавливается таблица стилей, то стили будут распространяться также на все дочерние элементы. В качестве селектора могут выступать:

    имя класса виджета. Стиль применяется ко всем элементам, которые могут быть приведены к классу с заданным именем;

    имя объекта определенного класса. Стиль применяется только к этому объекту;

    имя класса и свойства объекта. Стиль применяется ко всем объектам класса, обладающими заданным свойством;

    вложенные виджеты. Можно задавать применение стилей к объектам, вложенным непосредственно в текущий, либо с произвольным уровнем вложенности.

    В игре стили применяются к объекту класса ScreenController, и автоматически будут распространены на все вложенные виджеты.

    В примере задается цвет фона для всех виджетов, параметры кнопок и текстового поля, а также цвет кнопок, находящихся в определенных псевдосостояниях. Стиль, примененный для QPushButton:disabled будет распространен на все неактивные кнопки.

    При использовании QSS необходимо заглядывать в документацию, чтобы проверить возможность стилизации свойств определенного типа виджета [2], кроме того, в документации описано огромное количество примеров [3].

    Анимация и звук в Qt

    Ежик плавно перемещается, за счет использования QPropertyAnimation, при этом сам ёж при перемещении машет лапками — проигрывается соответствующая .gif-анимация (QMovie).

    Любой элемент игры отображает какую-либо анимацию, поэтому в класс Block включены соответствующие поля и метод установки анимации.

    Класс блок агрегирует экземпляр QLabel, на котором и отображается анимация. QMovie поддерживает кеширование, которое по умолчанию отключено. При кешировании, в память помещается не следующий кадр, а пачка кадров, поэтому сокращаются затраты на их переключение. В приведенном фрагменте используется метод jumpToFrame(), устанавливающий текущий кадр, который не должен использоваться при включенном кешировании, однако в нашем случае он производит лишь установку начального кадра анимации и никогда не переключает кадры во время проигрывания.

    Я уже рассказывал про графическую сцену в Qt [4], но в тот раз на сцене размещались экземпляры QGraphicsItem, но они не являются наследниками QWidget и не могут включать в себя виджеты (которым является QLabel, используемый для отображения анимации). В связи с этим, все наши ежи и облачка являются виджетами, а вместо QGraphicsScene::addItem() используется метод QGraphicsScene::addWidget(), создающий экземпляр QGraphicsProxyWidget, который и добавляется на сцену. Независимо от того, в какой позиции находился виджет до добавления, на сцене он окажется в левом верхнем углу. При добавлении на сцену QGraphicsProxyWidget копирует состояние исходного виджета, после этого состояние виджета всегда будет соответствовать состоянию прокси и наоборот — например, если скрыть виджет методом hide() — то скрыт будет и соответствующий прокси. При освобождении памяти из под прокси, будет удален исходный виджет. У класса QWidget имеется метод для получения соответствующего прокси — QWidget::graphicsProxyWidget().

    В нашей игре, за добавление виджетов на сцену отвечает виртуальный метод GameWidget::itemAdd(), принимающий тип добавляемого виджета и создающий экземпляр соответствующего класса. В классе GameHelpWidget этот метод перегружается для обработки элементов нового типа. После добавления элемента на сцену, выполняется метод move(), т.к. иначе виджет останется в левом верхнем углу сцены.

    Класс QPropertyAnimation позволяет анимировать свойства объекта, при этом указываются начальное и конечное значения свойства и время, за которое изменение должно произойти. QPropertyAnimation рассчитывает новое значение свойства, а по приходу сигнала от таймера (который есть внутри любого QObject) изменяет свойство и запрашивает перерисовку объекта. Под свойствами тут имеется ввиду любое Q_PROPERTY, в том числе, определенное пользователем — так, например, если бы мы разрабатывали виджет, моделирующий работу чашечных весов, рационально бы было определить угол наклона весов в виде свойства, а анимацию поворота рычага выполнять с помощью стандартного QPropertyAnimation. В нашей игре требуется плавно изменять координаты ёжика, а по окончанию анимации выполнять проверки на счет того, что ёж мог оказаться в тупике — проиграл, или обошел все клетки — выиграл.

    В конструкторе QPropertyAnimation указывается объект, свойство которого требуется изменять и имя свойства. Кроме того, может быть указан родительский объект, при разрушении которого из под анимации будет освобождена память — это удобно, если время проигрывания анимации совпадает со временем жизни какого-то объекта, но т.к. у нас такого класса нет — память освобождается в слоте-обработчике завершения анимации.

    Во время перемещения ежа проигрывается трек с топотом. Для проигрывания звука используем класс QMediaPlayer.

    QMediaPlaylist позволяет создать список проигрывания и управлять ими. В приведенном фрагменте трек всего один, а QMediaPlaylist используется для зацикливания проигрывания музыки.

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

    • пришлось отказаться от QMovie и анимации в gif-формате, т.к. пользователи телефонов начали жаловаться на низкое качество картинки, обусловленное сжатием gif;
    • исходный код был улучшен с точки зрения гибкости и удобства добавления новых возможностей — я планировал доработать игру добавив новые типы блоков, но руки не дойдут до этого — основная проблема в художнике, который опять попросит кучу денег за анимации и в огромном количестве времени, которое придется потратить на составление новых уровней;

    Скачать игру и ее исходный код можно в по ссылке.

    Урок №1. Введение в Qt и установка Qt Creator

    Обновл. 1 Сен 2020 |

    В этом уроке мы познакомимся с кроссплатформенным фреймворком Qt и установим IDE для работы с ним.

    Введение в Qt

    Qt является кроссплатформенным (не зависящим от платформы/ОС) фреймворком для разработки приложений на языке С++. С помощью Qt были разработаны такие известные приложения, как: KDE, Opera, Google Earth и Skype. Впервые Qt был опубликован в мае 1995 года.

    Qt5 подразумевает двойное лицензирование, а это означает, что Qt может быть использован в некоммерческих целях для создания приложений с открытым исходным кодом, а также как лицензия для коммерческих клиентов. За счёт использования собственного фреймворка и мощного инструментария Qt позволяет быстро и удобно создавать собственные кроссплатформенные приложения. Кроме того, команды разработчиков получают возможность работать на разных платформах, используя при этом общие инструменты для разработки и отладки. Весь инструментарий Qt с открытым исходным кодом вы можете найти на сайте qt.io.

    Изначально Qt был разработан Норвежской компанией по разработке программного обеспечения Trolltech. В 2008 году компанию приобрела Nokia. Спустя четыре года в августе 2012 программные технологии Qt выкупила финская компания-разработчик Digia. Сейчас Qt развивается компанией QT Company, которая являющейся дочерней компанией Digia, и как проект Qt под открытым исходным кодом, с участием отдельных разработчиков и фирм.

    Установка Qt Creator в Linux

    Шаг №1: Мы будем устанавливать IDE с открытым исходным кодом. Для этого переходим по ссылке и выбираем самую последнюю версию Qt 5.13:

    В этих уроках используется операционная система Linux (Debian 9.x 64-bit), поэтому мы скачиваем qt-opensourse-linux-x64-5.13.0.run , но вы также можете использовать соответствующие файлы Qt для Windows или Mac:

    После окончания загрузки переходим в папку с необходимым нам файлом, нажимаем по нему правой кнопкой мыши и выбираем «Свойства». В закладке «Основные» видим «Имя», «Тип», «Размер файла», а также наименование родительской папки:

    Переходим на вкладку «Права» и ставим галочку в поле «Разрешить выполнение файла как программы»:

    Закрываем «Свойства» и запускаем программу.

    Шаг №2: На следующем этапе установщик сообщает, что нам предоставлена версия с открытым исходным кодом Qt 5.13.0. Дальнейшая установка Qt предполагает регистрацию в Qt и создание Qt Account, который предоставляет доступ ко всем возможностям Qt. Кроме того, данное действие необходимо для проверки лицензии (коммерческая/некоммерческая). Если у вас уже есть учётная запись в Qt Account, то используйте кнопку «Next».

    Если учётной записи в Qt Account у вас ещё нет, то её можно создать сейчас: для этого перейдите по соответствующей ссылке в установщике, и вы будете перенаправлены на сайт qt.io в соответствующий раздел, или просто используйте кнопку «Next» — вы сможете это сделать в следующем шаге:

    Шаг №3: Здесь необходимо ввести логин и пароль от Qt Account или создать Qt Account, если его ещё нет. Кнопка «Next» переводит нас на следующий этап:

    Добро пожаловать в настройки Qt 5.13.0! Для перехода к следующему шагу нажимаем «Далее»:

    Шаг №4: Выбираем каталог для установки Qt 5.13.0. Обратите внимание, адрес каталога указывается латинскими буквами (без кириллицы) и без пробелов! После того, как выбрали каталог, нажимаем «Далее»:

    Шаг №5: Выбираем компоненты, которые хотим установить. Если на данном этапе нет уверенности в выборе конкретных компонентов, то добавление и удаление можно будет сделать позже, после установки программы:

    Шаг №6: Принимаем лицензионное соглашение:

    И нажимаем на кнопку «Установить»:

    Для завершения установки нажимаем «Завершить». После завершения загрузки Qt Creator запустится самостоятельно (для этого необходимо по умолчанию оставить галочку в поле «Launch Qt Creator»):

    Вот примерно следующее вы должны увидеть при запуске Qt Creator:

    Поздравляем! Qt Creator установлен.

    Установка через командную строку в Linux

    Ещё одним альтернативным и простым способом установки Qt Creator в Linux на основе Debian является установка из пакетов. Если при работе с Linux вы используете терминал, то перед скачиванием и установкой Qt Creator программа запросит пароль sudo пользователя. Только после этого начнётся скачивание и извлечение файлов. Обычно пакты Linux не содержат последней версии Qt и их необходимо обновить. Ниже приведен алгоритм действий, позволяющий за 4 шага установить Qt Creator через терминал.

    Шаг №1. Обновление:

    $ sudo apt update

    Шаг №2. Скачивание и установка Qt:

    $ sudo apt install qt5-default

    Шаг №3. Установка Qt Creator:

    $ sudo apt install qtcreator

    Шаг №4. Исходники:

    $ sudo apt install qtbase5-examples qtdeclarative5-examples

    Установка Qt Creator в Windows

    Перво-наперво нам нужно скачать установочный пакет Qt. Вы можете это сделать, обратившись к официальному сайту qt.io. Либо же воспользоваться альтернативным вариантом и скачать с какого-нибудь «зеркала», например c этого (полный список всех «зеркал» находится здесь):

    Нажимаем на official_releases/ и переходим к online_installers/ :

    Нажимаем на online_installers/ и скачиваем файл qt-unified-windows-x86-online.exe :

    Запустив скачанный файл, видим перед собой приветствие «Qt Online Installer». Нажимаем Next :

    Далее у нас спросят о наличии Qt-аккаунта. Можно смело нажимать Skip и двигаться дальше:

    Затем снова Далее :

    Теперь нам нужно указать путь установки Qt. Для простоты я выбрал C:\Qt :

    На следующем шаге нам нужно выбрать набор компиляторов, которыми мы будем пользоваться в наших уроках. Я предлагаю ограничиться выбором пакета MinGW 7.3.0 32-bit , а остальные метки поставить так, как указано на скриншоте ниже:

    После того, как инсталлятор скачает и установит все необходимые компоненты, можно будет перейти к непосредственному написанию кода для нашего приложения.

    Создание проекта

    Вначале нам необходимо создать проект. Сразу скажу, что наша программа будет консольным приложением. Для этого выберите Файл > Создать файл или проект… или можно воспользоваться сочетанием клавиш Ctrl+N :

    Перед вами появится «Мастер настройки проектов». В левой колонке отметьте пункт Приложение , а затем в правой — Консольное приложение Qt :


    На следующем шаге нужно будет указать имя для нашей будущей программы и папку, где будут располагаться файлы проекта. У меня это My_QtApplication и C:\dev\Qt_Project соответственно:

    На следующем шагу без изменений, поэтому просто нажимаем кнопку Далее :

    Теперь нам нужно выбрать набор компиляторов, который мы будем использовать для сборки своего проекта. Я настоятельно вам рекомендую выбрать Desktop Qt 5.13.0 MinGW 32-bit (сняв при этом отметки с остальных, если они у вас есть):

    На последнем шагу нажимаем Завершить :

    Теперь вы можете увидеть автоматически сгенерированный Qt-проект консольного приложения. Давайте рассмотрим его подробнее:

    KNZSOFT Разработка ПО, консультации, учебные материалы

    Князев Алексей Александрович. Независимый программист и консультант.

    Qt для начинающих. Урок 1. Простейшее GUI-приложение и основные виджеты

    Вернуться к общему содержанию «Qt для начинающих».

    Чтобы первый урок был более интересным, построем его на ряде примеров с пояснениями.

    Простой пример для ручной сборки

    Для лучшего понимания Qt будет правильным выполнить ручную сборку в консоли хотя бы простейшего примера. Методика сборки одинакова для проектов любого размера и важно понимать, как она выполняется.

    Рассмотрим простейший пример GUI-приложения, которое выполняет открытие пустого окна на экране. Выделим директорию на диске, где создадим файл main.cpp со следующим содержимым. В пример добавлена нумерация строк для упрощения дальнейших комментариев к примеру. Следует понимать, что нумерация строк не должна содержаться в рабочем файле, так как она не входит в допустимый синтаксис выражений на языке C++.

    В строках 01 и 02 выполняется включение заголовочных файлов QApplication и QWidget, в которых, кроме прочего, содержится объявление классов QApplication и QWidget. В нашем примере мы создаем экземпляры этих классов.

    Следует заметить удобную традицию именования заголовочных файлов используемую в Qt. Начиная с четвертой версии Qt, если вам потребовался класс с именем Qxxx, то, скорее всего, его определение находится в заголовочном файле Qxxx.

    В данном примере, класс QApplication интересует нас как организатор цикла сбора сообщений, которые будут приходить в окно нашего GUI-приложения. См. строку 11 (запуск цикла обработки оконных сообщений). Класс QApplication реализован по подобию синглтона (Singleton). Для тех, кто не знаком с этим термином из теории шаблонов проектирования (или, паттернов, от англ. patterns) дадим небольшое пояснение. Суть синглтона заключается в том, что реализация класса предотвращает возможность создания более одного экземпляра данного класса. Эта особенность нам важна потому, что из нее следует возможность определения внутри библиотеки Qt глобальной переменной с указателем на единственный экземпляр данного класса. Смотрите описание для символа qApp в справке Qt.

    В библиотеке Qt используется терминология виджета (от англ. widget — штуковина, приспособление), как элемента GUI-интерфейса. Минимальный общий набор свойств таких элементов представлен классом QWidget.

    В строках 06 и 07 создаются объекты классов приложения и виджета. В обоих случаях выполняется статическое создание объектов. Время существования таких объектов ограничивается операторным блоком < … >в котором они созданы. Как только исполнение кода программы дойдет до закрывающей скобки, то оба этих объекта автоматически уничтожатся. Таким образом, в данном примере мы не будет задумываться о способе уничтожения объектов Qt и рассмотрим этот вопрос позже.

    При создании объекта QApplication используется параметризованный конструктор в который передаются аргументы запуска приложения (копируются из аргументов функции main()). Внутри объекта класса выполняется парсинг этих аргументов. Класс приложения поддерживает ряд параметры запуска, которые можно уточнить по справке для соответствующего конструктора QApplication. Параметры запуска не входящие в этот список следует анализировать самостоятельно. В конце этого урока, разместив в главном окне приложения несколько элементов управления мы предложим провести эксперимент с параметром запуска -style, для которого, в любой сборке Qt, возможны значения: motif, windows, platinum.

    В строке 08 выполняется изменение одного из атрибутов объекта виджета. С помощью метода setWindowTitle() мы устанавливаем свой текст для заголовка нашего будущего окна. Обратите внимание, что изображение строки обернуто вызовом функции трансляции tr(). Это требование интернационализации приложения. По всем подобным оберткам, специальными средствами Qt, могут быть созданы специальные файлы с переводами на разные языки, которые можно будет использовать в приложении для выполнения автоматических замен. Обычно, такие файлы включают в сборку приложения в виде ресурсов.

    В строке 10 выполняется открытие окна приложения. До версии Qt4, перед открытием окна выполнялась явное объявление виджета как главного виджета приложения. Это делалось с помощью следующего кода.

    Начиная с версии Qt4 выполнение такой связи выполняется автоматически через обращение к глобальному указателю qApp на экземпляр класса приложения.

    В строке 11 выполняется запуск цикла обработки сообщений операционной системы направленный в окно приложения. Цикл завершается при выполнении какой-нибудь из команд закрытия приложения. Код закрытия приложения возвращается методом exec() при завершении метода. Именно этот код становится кодом возврата функции main() за счет передачи его через оператор return.

    Теперь попробуем выполнить сборку приложения. Проще всего это будет сделать в Linux. Для этого надо будет просто открыть консоль и выполнить некоторые команды, которые мы сейчас опишем. Для Windows такая работа может потребовать установку путей на директории размещения утилиты qmake из Qt SDK. Данная утилита реализует правила системы сборки проектов QMake.

    Для начала следует узнать, что нам доступно из консоли. Если мы в консоли bash (*nix), то сделать это достаточно просто. Наберите команду qmake и нажмите два раза табуляцию. Мы должны увидеть список всех команд, которые начинаются с сочетания qmake. Например, в моем случае я вижу две команды: qmake и qmake-qt4. Это говорит о том, что у меня из репозитория установлены две версии библиотеки. Команда qmake соответствует версии Qt5 (действует умолчание для последней версии), а команда qmake-qt4 соответствует, соответственно Qt4. Теперь, в зависимости от того, какой командой я воспользуюсь, я буду делать сборку либо с использованием версии Qt5, либо с использованием версии Qt4.

    Если все у нас в системе настроено нормально и версии Qt SDK удачные, то сборка проекта должна быть выполнена с помощью следующих трех команд.

    С помощью первой команды будет создан проектный файл. Проектный файл имеет суффикс .pro. В контексте Windows правильно будет сказать «расширение pro«. Понятия суффикс имени файла и расширение файла означают совершенно разные вещи, хотя и кажутся похожими. Следите за правильностью употребления.

    Вторая команда должна создать файл сценария компиляции — Makefile. Третья команда должна выполнить сценарий компиляции, в результате которого должен получиться исполняемый файл приложения.

    Если этого не произошло, то попробуем найти проблему.

    Откройте проектный файл. Попробуйте найти там следующую строку.

    Если такой строки там нет, то следует ее добавить, иначе в зависимости от версии SDK проект может быть воспринят как консольный и в него не будут включены пути на заголовочные файлы классов GUI. Это приведт к тому, что при компиляции будут выведены ошибки о том, что включенные заголовочные файлы не найдены.

    Следует иметь в виду, что если вы имеете дело с Qt SDK версии 5, то данное определение должно еще включать группу widgets, как показано ниже.

    Пример создания шаблона GUI-приложения из QtCreator

    Откройте QtCreator. Для создания нового проекта запустим мастер создания проекта из меню «File->New File or Project …». В открывшемся окне первой страницы мастера предлагается выбрать шаблон будущего проекта. Для группы проектов «Application» выберем вариант «Qt GUI Application» и щелкнем по кнопке «Choose» для перехода на следующую страницу мастера.

    На второй странице мастера создания проекта предлагается выбрать имя проекта и директорию его размещения. По указанному имени проекта будет создана поддиректория в которой будут размещены файлы проекта. Создание поддиректории будет выполнено в указанной директории размещения. Таким образом, имя проекта должно определяться правилами которым должно подчиняться имя директории. Однако, чтобы избежать проблем, не используйте русских букв и пробелов. Используйте английские буквы, цифры и символы подчеркивания и тире (знак минуса). Пусть наш проект будет называться app1. Запишем его в строку name, а в строке выбора директории проекта укажем директорию, где и в дальшейшем будем создавать проекты на Qt. Следует избегать путей с русскими буквами и пробелами. Рано или поздно, они могут вызвать проблемы. Если необходимо запомнить этот путь для следующего раза, установите флажок «Use as default project location». Щелкнем по кнопке «Next» для перехода на следующую страницу мастера.

    На третьей странице мастера создания проекта предлагается выбрать Qt SDK из списка найденных и зарегистрированных в QtCreator. Выберите вариант Qt4. Для выбранной версии SDK, следует определить профили сборки проекта. Предлагаются варианты «Release» и «Debug» Сборка «Release» не содержит отладочных символов в исполняемом файле и рекомендуется для передаче в реальное использование. Во всех остальных случаях, удобнее использовать сборку «Debug». В текущем примере, выбор сборки не имеет значения. Можно оставить включенным оба профиля. Справа от названия профиля расположено поле ввода в котором записан путь по которому будет выполняться соответствующая сборка. Часто эти пути редактируют исходя из разных традиций. В нашем примере мы можем оставить эти пути без изменений. Щелкнем по кнопке «Next» для перехода на следующую страницу мастера.

    На четвертой странице мастера создания проекта предлагается выбрать имя класса для главной формы проекта, базовый класс, от которого следует унаследовать главную форму проекта и имена файлов, где будет размещен интерфейс и реализация создаваемого класса главной формы. Кроме этого, на странице следует указать будет ли использовано визуальное проектирование формы. Так как мы не будем использовать визуальное проектирование, то следует проследить, чтобы флажок «Generate form» был снят.

    Наиболее интересным на четвертой странице мастера создания проекта является выбор базового класса для создания класса формы. Предлагаются три варианта.

    1. QMainWindow — в большинстве случаев, наиболее подходящий выбор. Наследуясь от данного класса мы получаем уже готовые средства для размещения меню, строки статуса и центрального поля, которое можно реализовать как в стиле SDI (Single Document Interface), так и в стиле MDI (Multi Document Interface).
    2. QWidget — этот класс является простейшим виджетом. В терминологии Qt это простейший элемент, с которым связана какая-то графическая область на экране. Как базовый класс для главного окна, используется, как правило, при создании простых одноформенных приложений и отлично подходит для начальных «ученических» целей по причине того, что не содержит ничего «лишнего».
    3. QDialog — базовый класс для создания модальных диалоговых окон.

    Для нашего примера, выберем в качестве базового класса, простейший вариант — QWidget. Имена для главного класса формы и для файлов, где будет размещаться его интерфейс и реализация можно оставить значениями по-умолчанию. Щелкнем по кнопке «Next» для перехода на следующую страницу мастера.

    Пятая страница мастера создания проекта позволяет определить связь создаваемого проекта с уже открытыми проектами и указать выбор какой-нибудь доступной системы управления версиями проекта. В текущем примере нас не интересуют данные возможности, поэтому нам следует завершить работу мастера щелкнув кнопку «Finish».

    В разных версиях QtCreator шаги по созданию проекта могут несколько отличаться, но, по сути, здесь изложены главные моменты, которые следует понимать при создании GUI-проекта. Текущее описание делалось на основе версии QtCreator 2.7.0.

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

    QtCreator заметно отличается своим дизайном от других сред разработки. Однако, его дизайн удивительно эргономичен. Кроме прочего, в эпоху широких экранов, очень выгодно смотрится панель инструментов расположенная слева в главном окне среды разработки. В нижней части панели инструментов, как уже говорилось, расположены кнопки запуска приложения, а в верхней — кнопки выбора вкладок для главного окна среды разработки. Рассмотрим список основных вкладок.

    • «Welcome» — Выбор проекта
    • «Edit» — Редактирование программы.
    • «Debug» — Отладки проекта. Включает необходимые окна для наблюдения за объектами.
    • «Projects» — Настроки проектов, загруженных в среду разработки. Следует внимательно изучить возможности представленные на этой вкладке
    • «Analyze» — Анализ проектов с помощью специальных средств обнаружения узких мест в быстродействии и проблем утечки памяти.
    • «Help» Окно интергрированной справки. Возможно, вам больше понравится работать с отдельным справочным приложением QtAssistant.

    Простой пример размещения виджетов в окне приложения

    Возьмем проект, который мы создали в предыдущем разделе с помощью мастера среды разработки QtCreator. Созданный проект включает в себя следующие файлы.

    • app1.pro — файл проекта
    • main.cpp
    • w > Возможно, имена файлов в вашем проекте несколько отличаются. Это может быть либо потому, что вы их явно указали другими, при создании проекта, либо значения по умолчанию для вашей версии QtCreator иные.

    Откроем файл реализации главного окна приложения — widget.cpp. Изменим его до состояния представленного в следующем примере. Помните, что номера строк указаны только для удобства комментариев.

    В строках 01-03 выполняется включение файлов с интерфесами следующих классов виджетов.

    1. QLabel — класс метки. Часто используется для размещения статической текстовой информации. Понимает некоторые теги HTML для форматирования. Может быть использован для статического размещения изображения. Например, из файла с картинкой. Наследуется от QFrame, поэтому может настраиваться на различные формы окантовки (бордюра).
    2. QLineEdit — класс для создания однострочных полей ввода текстовой информации.
    3. QPushButton — класс кнопки. Чаще всего используется для обработки сигнала clicked() — щелчок по кнопке.

    Тело конструктора класса Widget содержит две строки настройки атрибутов окна (строки 10-11) и 8 строк создания и размещения на поле окна трех других виджетов (строки 13-20).

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

    Строка 13 содержит создание экземпляра класса QLabel. Объект создается динамически, через оператор new. Для создания объекта используется конструктор, первым параметром которого указывается строка, которую должен изображать создаваемый объект. Вторым параметром данного конструктора следует указать адрес объекта, который станет владельцем создаваемого объекта метки. В качестве адреса владельца указано значение this. По правилам языка C++, this является указателем на объект внутри которого он используется. Т.е., в данном контексте, это указатель на созданный экземпляр класса Widget. Таким образом, в строке 13 создается объект класса метки, который должен изображать указанный текст и владельцем которого назначается текущий объект.

    Здесь пришло время рассказать о цепях владения, которые реализованы в системе классов Qt для решения проблемы уничтожения объектов для предотвращения случайных утечек памяти. Следует вспомнить, что объекты созданные динамически, т.е. с помощью оператора new, размещаются в специальной области памяти, называемой кучей (heap) и которые живут в куче до тех пор пока не будут явно уничтожены оператором delete. Если программист не отслеживает уничтожение объектов, которые стали ненужными и не вызывает для их уничтожения оператор delete, то это становится причиной утечки памяти в приложении, которая является серьезной проблемой для ряда языков программирования в группу которых входит язык C++.

    Существует несколько известных схем автоматического слежения за уничтожением динамически созданных объектов. Один из них заключается в использовании умных указателей, о которых, следует рассказать позже. Другой способ заключается в создании цепей владения, о котором мы сейчас расскажем. Третьим способом является создание подсистемы уборки мусора, которая должна отлеживать ненужные объекты и уничтожать их. Последний способ, традиционный для ядер многих современных языков, в C++ практически не используется. Гораздо более популярными в традициях языка C++ являются первые два способа.

    Итак, цепи владения реализуют следующую простую идею. Создается некоторый объект, за уничтожением которого мы обязуемся следить. Проще всего создать такой объект статическим определением и тогда он уничтожится автоматически, когда исполнение программы достигнет конца операторного блока < … >в котором он был определен. Далее, при динамическом создании других объектов будем назначать для них объекты владельцев. В обязанности владельцев будет входить уничтожении владеемых объектов в теле собственного деструктора. Напомним, что деструктор — это особый метод, который вызывается при уничтожении объекта. Таким образом, можно построить такую цепь владения относительно первого объекта, все элементы которой будут автоматически уничтожены при уничтожении первого объекта. При организации такой схемы следует лишь правильно учитывать время жизни объекта, который назначается владельцем другого объекта, чтобы объекты не были уничтожены преждевременно.

    Именно такая схема владения реализована в системе классов Qt. При создании многих классов из этой библиотеки можно воспользоваться конструктором, который единственным или последним параметром принимает указатель на объект, который назначается владельцем к создаваемому объекту. Параметр этот описывается как параметр со значением по умолчанию, которое определяется как ноль. Таким образом, если адрес владельца не указывается, то параметр получает значение ноль и схема владения для такого объекта отключается. В этом случае следует помнить о явном уничтожении такого объекта.

    При реализации схем цепей владения, в некоторых библиотеках используется параметр с именем owner, что с английского языка переводится как владелец. Однако в библиотеке Qt такой параметр называется parent, что переводится с английского как родитель. В результате этого, у некоторых новичков возникает недопонимание образованное тем, что понятие «родитель» традиционо относится к цепям наследования в ООП, однако цепи наследования и цепи владения не имеют ничего общего. Будьте внимательны и не становитесь жертвой заблуждения в этом вопросе.

    Вернемся еще раз к строке 13. Там мы создали объект владельцем которого назначен текущий объект главного окна приложения. Переменная plb, которая хранит адрес созданного объекта будет уничтожена автоматически при достижении конца кода конструктора. Однако объект который был распределен в памяти останется жить и далее, и будет жить до тех пор, пока объект главного окна приложения не будет уничтожен. При уничтожении объекта главного окна будут автоматически уничтожены все объекты, которыми объект окна владеет.

    В строке 14 мы обращаемся к методу задания атрибутов геометрии, которые определяют размещение настраиваемого объекта относительно своего владельца. Первым и вторым значением указываются горизонтальная и вертикальная координата для верхнего левого угла объекта. Третьим и четвертым значением указывается ширина и высота настраиваемого объекта.

    Аналогичным образом, далее, создаются и настраиваются объекты однострочного поля ввода и кнопки.

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

    Используя данное приложение можно поэкспериментировать с параметрами запуска приложения. Проще всего это сделать в консоли. Зайдите в директорию сборки приложения и выполните следующие варианты запуска приложения с параметрами. В каждом из запусков должна быть заметна разница в стиле прорисовки виджетов.

    В данном примере, исполняемый файл приложения указан именем app1. Возможно, что в вашем случае, исполняемый файл имеет другое имя. В операционной системе Windows, исполняемые файлы имеют расширение exe. Кроме того, в операционной системе Windows, выполнить запуск исполняемого файла из текущей директории можно без указания относительного пути, т.е. без указания (./) — символ точки является синонимом текущей директории, а символ прямого слеша — символом разделителя в записи файловых путей. Также, следует иметь в виду, что символ доллара — это символ стандартного приглашения в консоли *nix для обычного пользователя и набирать его частью команды не нужно. В консоли Windows, символом приглашения обычно является символ угловой скобки (>).

    Параметры запуска, также можно указать при запуске приложения из среды разработки QtCreator. Для этого щелкните на панели инструментов слева по значку Projects. Откроется соответствующая вкладка с настройками. В верхней части окна можно видеть иерархическую систему вкладок. Вкладки самого верхнего уровня определяют проект, так как в среде разработки могут быть открыты несколько проектов. Следующий уровень вкладок, кроме прочего, должен содержать вкладку Build&Run, которая нам нужна. В этой вкладке далее следует выбор версии Qt SDK, для случая, если вы делаете сборку проекта сразу под несколько версий. Если вы собираете проект под одну версию, то выбор будет состоять из одного элемента. Внутри виджета выбора версии Qt SDK, расположены две стилизованные кнопки с закругленными краями — кнопки Build и Run. Щелкните по кнопке Run, чтобы выбрать соответствующую группу настроек. Там, в одноименной группе параметров Run вы найдете однострочное поле ввода напротив метки Arguments. Это и есть конечная цель нашего выбора. Запишем туда следующую строку.

    Запустите приложение. Потом попробуйте другие значения: windows и platinum. Напомним, что объект класса QApplication поддерживает список из пары десятков параметров запуска, о которых можно прочитать в справке по соответствующим конструкторам класса.

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

    1. QComboBox — класс выпадающего списка.
    2. QCheckBox — класс флажка (чекера).
    3. QTextEdit — класс многострочного поля ввода. Используется как для редактирования, так и для представления текста. Содержит очень богатые возможности по представлению документов за счет выделения функций специальных компоновщиков документов в отдельные классы.

    В заключении урока следует заметить, что используемый способ «жесткого» размещения объектов на поле формы, через явное указание геометрии размещения не является традиционным и рекомендуемым в библиотеке классов Qt. В следующих уроках будут рассмотрены менеджеры компоновки, которые являются современными и удобными средствами размещения виджетов на форме.

    Добавить комментарий Отменить ответ

    Для отправки комментария вам необходимо авторизоваться.

    Пишем игру «Жизнь» под Android используя C++ и Qt за час.

    Всем привет! Недавно видел на пабликах типа ТП посты мол «делаем игру жизнь на java за час», «делаем игру жизнь на python за час», вот решил сделать пост, делаем игру жизнь под андроид используя C++ и библиотеки Qt за час.

    Важно отметить что игра занимает

    100 строчек кода(исключая h файлы, символы переноса и т.п.), а также то, что созданная игра будет работать и под винду, и под андроид, и под линукс, и под ios и под mac os x.

    И так начнем. Правила игры жизнь я думаю вы знаете. Есть поле с клетками. Клетка может быть живая или мертвая. По прошествии хода, если вокруг мертвой клетки есть 3 живых, она становится живой. Если вокруг живой клетки будет 1 или 0 живых, то она становится мертвой, также она становится мертвой если вокруг нее более 3 живых клеток. Впринципе все, подробнее вы можете прочесть на википедии.

    И так что у нас должно быть:

    Поле с N*M клеток, кнопка «Новая игра», кнопка «Начать эволюцию». Поле забито прямогуольниками, изначально все пустые. При нажатии на клетку она окрашивается в черный или белый цвет, в зависимости от того какой цвет был там раньше.

    2. Логика. Мы должны иметь двумерный массив(используем QT’шный вектор), в котором 0 отмечена мертвая клетка а единицей живая клетка. У меня была цель создать игру примерно за час, и поэтому этот 0 и 1 соответствуют черному и белому цветам многоугольников. Соответственно у нас есть массив с указателями на наши прямоугольники. Это не хорошо, ибо логика должна быть отделена от GUI, но для уменьшения размера кода — решил сделать так.

    Должны быть реализованы функции подсчета соседей для каждой из клеток, зная положение клетки по X и Y. После каждого хода, мы рассчитываем количество соседей для каждой из клеток, и в зависимости от состояния клетки и количества её соседей добавляем клетку в массив(вектор), для изменения её состояния. Если за 1 ход не было добавлено ни 1 клетки, то игра заканчивается, выводим пользователю количество ходов

    Если вы не знакомы с наследованием и библиотекой STD в C++, то вы являетесь новичком в C++ и возможно код покажется вам запутанным. К сожалению не хотелось бы писать про все это в этом посте, ибо для новичков информации в интернете — тонны, а переписывать еще раз это — просто не зачем. Если вы с этим знакомы, но незнакомы с сигнально-слотовой системой Qt тоже порекомендую прочитать over9000 материалов по этой теме. Если потребуются пояснения я отвечу в комментах.

    И так, как выглядит GUI:

    Скачиваем Qt Creator с официального сайта Qt(qt.io), выбираем бесплатный вариант для GPL приложений. Запускаемся, создаем новый проект, используя QWidget, с графической формой

    Переходим к созданию. Переходим в режим дизайн и добавляем на форму «Graphics View» и 2 Push Button. Примерно вот так как на следующей картинке, и кликая правой кнопкой мыши по форме выбираем (Скомпоновать по сетке)

    GUI готово! Теперь нам нужно перейти к непосредственно программированию.

    QGraphicsView — это виджет, который может отображать графические элементы. QGraphicsView отображает элементы, который расположены на QScene. На QScene мы размешаем элементы в декартовой системе координат, а с помощью QGrahicsView мы её отображаем(можно поворачивать, увеличивать масштаб и т.п.).

    Элементы бывают разных типов. Есть простые — QGraphicsRectItem — это многоугольник, который к слову нам и понадобиться. Есть QGraphicsPixMapItem который отобразит нам изображение. Есть QGraphicsLineItem — это линия. И другие.

    И так, первая задача. Разместить на сцене N*M QGraphicsRectItem’ов — наших клеток. Мертвой клеткой будет считаться клетка, с Kletka->brush().color() == Qt::white живой Kletka-> brush().color() == Qt::black. И запихнуть все указатели на QGraphicsRectItem в отдельный двумерный вектор, чтобы мы могли с ними работать.

    Однако, для этой задачи нам не подойдет «чистый» QGraphicsRectItem. Нужно будет создать класс наследник, и в нем реализовать свою обработку нажатия на клетку. Ведь в самом начале игры нам нужно будет выставить первичные мертвые и живые клетки на поле.

    Т.е. по нажатию на наш прямоугольник, он должен окрашиваться в требуемый цвет. А у чистого QGraphicsRectItem обработка данного события пустая.

    Создадим класс LifeRect основанный на QGraphicsRectItrem., и переопределим в нем mousePressEvent

    Теперь займемся реализацией. Конструктор будет использовать конструктор с такими же параметрами как у QGraphicsRectItem(позиция по x, позиция по y, широта, высота, родитель). В событии mousePressEvent будет вызываться функция changeColor.

    И так, переходим дальше. Работаем с нашим виджетом(формой) — widget.c. В этом классе реализуется логика игры.

    Что нам необходимо?

    1. Таймер. Каждые 0.1 секунды будет происходить 1 ход.

    2. Слоты нажатия на кнопку «Старт» и «Новая игра» соответственно.

    3. Размеры поля — X и Y клеток. Принимаются через конструктор.

    4. Переменная для хранения количества итераций(для вывода при завершении игры)

    5. Двумерный вектор(используется QVector, а не std::vector) который хранит указатели на созданные нами LifeRect’ы. К его элементам мы будем обращаться, и будем представлять живое и мертвое состояние по его цвету, как я уже и писал ранее. Если среди читателей будут новички C++ в комментах могу помочь. Просто представляйте что это массив.

    6. Функция для новой игры(обнуление поля, обнуления количества итераций).

    7. Функция подсчета живых соседей рядом.

    И так, начнем. Собственно вот заголовочный файл:

    В конструкторе присвоим начальные данные(x,y из входных, 0 итераций, укажем то что сцена пока-что пустая, родительский элемент отсутствует. Проинициализируем таймер, но запускать его не будем

    Создать слот on_pushButton нужно нажав правой кнопкой по кнопке на форме, выбрать перейти к слоту, и выбрать сигнал clicked()

    Дальше — интереснее. И так, по нажатию на кнопку новая игра, мы должны нарисовать графическую сцену, с X*Y мертвыми многоугольниками, и наполнить двумерный вектор указателей на многоугольники ими же. Чтобы потом,когда игрок заполнит поле и нажмет на кнопку «СТАРТ» запускается таймер, по каждому тику таймера обходить этот вектор, вычислить количество живых соседей каждой клетки, и перерисовать требуемые.

    Постарался максимально прокомментировать код.

    К слову говоря, позиции осей X и Y в графической сцене таковы:

    И так, мы прорисовали свои элементы, и уже можем потыкать и поменять их цвета, но пока-что не можем ничего запустить. Нужно реализовать функцию обработки каждого хода. И написать что по 2 кнопке мы запускаем таймер.

    Осталось лишь только реализовать функцию подсчета соседей. Думаю, в ней проблем не будет. Мы просто смотрим на цвета наших 8 соседей(если вылезли за границы то перемещаемся в начало или конец соответственно) и выдаем на выход их количество

    Все готово! Запускаем и играем на Linux, Windows или вашем Mac.

    Что потребуется(если вкратце) для запуска на Android?

    1. Пакеты Android SDK и Android NDK(для C++).

    2. Устройство андроид или AVD.

    Вы должны сконфигурировать ваш Qt Creator, в таком виде(ваши пути), и добавить в проектах сборку Android. Потребуется скачать в AVD драйвера USB, и API требуемых версий Android. Затем уже попробовать установить приложение на телефон/эмулятор. Я могу помочь, или привести ссылки где это подробно разбирается в комментах

    Пробуем на стареньком LG Optimus One с Andro >

    Программирование на языке C++ в среде Qt Greator. Е. Алексеев

    Книга является учебником по алгоритмизации и программированию на С++ и пособием по разработке визуальных приложений в среде Qt Creator.
    Также в книге описаны среда программирования Qt Creator, редактор Geany, кроссплатформенная билиотека построения графиков MathGL.
    При чтении книги не требуется предварительного знакомства с программированием.
    Издание предназначено для студентов, аспирантов и преподавателей вузов, а также для всех, кто изучает программирование на С++ и осваивает кроссплатформенный инструментарий Qt для разработки программного обеспечения.

    Если вам понравилась эта книга поделитесь ею с друзьями, тем самым вы помогаете нам развиваться и добавлять всё больше интересных и нужным вам книг!

    Часть 1. Введение. Инструменты разработчика и объектная модель

    Серия контента:

    Этот контент является частью # из серии # статей: Программирование с Qt

    Этот контент является частью серии: Программирование с Qt

    Следите за выходом новых статей этой серии.

    1. Введение

    Существуют версии Qt для unix-подобных операционных систем с X Window System (например, X.Org (EN), Mac OS X и ОС Windows). Также Qt Software портирует свой продукт на мобильные платформы: Embedded Linux (EN), S60 (EN) и Windows CE. Qt предоставляет большие возможности кросс-платформенной разработки самых разных программ, не обязательно с графическим интерфейсом. На нем, в частности, основана популярная среда рабочего стола KDE (EN).

    Инструментарий разбит на модули, каждый из которых размещается в отдельной библиотеке. Базовые классы находятся в QtCore , компоненты графических интерфейсов – в QtGui , классы для работы с сетью – в QtNetwork и т.д. Таким образом, можно собирать программы даже для платформ, где нет X11 или другой совместимой графической подсистемы.

    2. Установка Qt

    Нам потребуется установить среду разработки Qt. Программное обеспечение распространяется на условиях свободной лицензии GPL 3.0 или LGPL 2.1. Его можно получить по адресу http://www.qtsoftware.com/downloads (EN).

    2.1. Базовые библиотеки и инструменты

    В репозиториях популярных дистрибутивов GNU/Linux уже есть готовые пакеты со средой разработки Qt (например, в Debian, Fedora, Gentoo, Mandriva, Ubuntu). Тем не менее, пользователь может собрать и установить инструментарий из исходных текстов.

    Для систем, использующих X11, необходимо загрузить файл qt-x11-opensource-src-4.x.y.tar.gz , где 4.x.y – последняя доступная версия из стабильных. Мы будем устанавливать версию 4.5.0.

    В директории с файлом qt-x11-opensource-src-4.5.0.tar.gz выполните следующие команды:

    Прежде чем собирать Qt, запустите скрипт configure . Полный набор его опций выдается по команде ./configure -help , но обычно можно использовать типовые настройки.

    Параметр -prefix задает каталог для установки (по умолчанию используется /usr/local/Trolltech/Qt-4.5.0 ). Также имеются ключи для инсталляции различных компонентов (исполняемых файлов, библиотек, документации, и т.д.) в разные директории.

    При запуске скрипт требует подтвердить согласие пользователя с условиями лицензии GPL / LGPL. После выполнения

    можно запустить сборку и установку при помощи команд:

    Имейте в виду, что компиляция занимает много времени, а для установки Qt могут потребоваться права суперпользователя (файлы записываются в /usr/local/ ).

    Если в дальнейшем вам понадобится в той же директории заново сконфигурировать и пересобрать Qt, удалите все следы предыдущей конфигурации при помощи make confclean , прежде чем снова запускать ./configure .

    Путь к исполняемым файлам Qt нужно добавить в переменную окружения PATH. В оболочках bash, ksh, zsh и sh это можно сделать, дописав в файл

    /.profile следующие строки:

    В csh и tcsh нужно дописать в

    Если вы используете другую оболочку, то обратитесь к соответствующим разделам документации.

    Кроме того, необходимо добавить строку /usr/local/Trolltech/Qt-4.5.0/lib в переменную LD_LIBRARY_PATH , если компилятор не поддерживает RPATH. Мы используем GNU/Linux и GCC (EN), поэтому пропускаем этот шаг.

    Затем с помощью утилиты qtdemo запустите демонстрационные приложения для проверки работоспособности установленного инструментария.

    2.2. SDK

    Недавно появилась кросс-платформенная среда разработки Qt Creator. На сайте Qt Software можно найти полный SDK, включающий IDE (помимо библиотек и основных средств разработчика). Загрузите бинарный файл qt-sdk-linux-x86-opensource-xxx.bin и запустите мастер установки:

    Если не собираетесь устанавливать SDK в домашнюю директорию, то запускайте инсталлятор с правами суперпользователя.

    Рисунок 1. Установка Qt SDK

    3. Инструменты разработчика

    В состав Qt включены инструменты разработчика с графическим или консольным интерфейсом. В их числе:

    • assistant – графическое средство для просмотра гипертекстовой документации по инструментарию и библиотекам Qt.
    • designer – графическое средство для создания и сборки пользовательских интерфейсов на основе компонентов Qt.
    • qmake – кросс-платформенный генератор Makefile.
    • moc – компилятор метаобъектов (обработчик расширений Qt для C++).
    • uic – компилятор пользовательских интерфейсов из файлов .ui, созданных в Qt Designer.
    • rcc – компилятор ресурсов из файлов .qrc.
    • qtconfig – графическое средство установки пользовательских настроек для приложений Qt.
    • qtdemo – запуск примеров и демонстрационных программ.
    • qt3to4 – средство переноса проектов с Qt 3 на Qt 4.
    • linguist – средство для локализации приложений.
    • pixeltool – экранная лупа.
    Рисунок 2. Qt Assistant


    Рисунок 3. qtdemo

    3.1. qmake

    Утилита qmake используется для автоматического генерирования Makefile на различных платформах.

    В целом qmake ориентируется на Qt. Если вас интересуют кросс-платформенные системы сборки более широкого назначения, то можете обратиться к CMake, которая также поддерживает Qt.

    Новичкам стоит остановиться на qmake.

    Полную документацию по этой утилите вы можете найти в Qt Assistant. Также с Qt поставляются страницы руководства, в том числе qmake(1) (наберите в командной строке man qmake ). Здесь мы приведем основные указания, которые помогут вам собирать код примеров статьи, а также свои простые проекты.

    В качестве примера создадим директорию myproject и добавим туда файлы hello.h, hello.cpp и main.cpp . В hello.h опишем прототип функции hello():

    Листинг 1.1. Объявления функций программы «Hello, World!»

    Реализацию hello() поместим в hello.cpp:

    Листинг 1.2. Реализации функций программы «Hello, World!»

    Здесь qDebug() используется для вывода отладочной информации. Ее можно убрать, объявив при компиляции символ QT_NO_DEBUG_OUTPUT . Также имеется функция qWarning() , выдающая предупреждения, и qFatal() , завершающая работу приложения после вывода сообщения о критической ошибке в STDERR (то же самое, но без завершения работы, делает qCritical() ).

    В заголовочном файле содержатся объявления, добавляющие для qDebug(), qWarning() и qCritical() более удобный синтаксис оператора . При этом между аргументами (как в случае qDebug() ) автоматически расставляются пробелы, поддерживается вывод многих типов C++ и Qt, а в конце автоматически добавляется перевод строки.

    Код основного приложения (здесь мы следуем соглашению, по которому main() помещается в файл main.cpp ):

    Листинг 1.3. Функция main() программы «Hello, World!»

    Чтобы создать файл проекта, запустите

    После этого должен появиться файл myproject.pro примерно такого содержания:

    Оператор = используется для присвоения значений переменным, += добавляет новую опцию к переменной, -= удаляет указанную опцию.

    TEMPLATE = app обозначает, что мы собираем приложение; для библиотеки используется TEMPLATE = lib .

    TARGET – имя целевого файла (укажите TARGET = foobar , чтобы получить исполняемый файл foobar ).

    DEPENDPATH – директории для поиска при разрешении зависимостей.

    INCLUDEPATH – директории с заголовочными файлами.

    на основе myproject.pro в GNU/Linux будет создан обычный Makefile :

    Опции qmake влияют на содержимое Makefile. Например, qmake -Wall добавит к флагам компилятора -Wall – вывод всех предупреждений.

    По команде make мы получим исполняемый файл myproject , который выводит на экран строку «Hello, World!».

    Эта схема может показаться слишком сложной, но в реальных проектах qmake берет на себя большую часть работы по сборке (например, запускает компилятор метаобъектов).

    3.2. Qt Creator

    Описанных выше инструментов достаточно для разработки приложений. Вы можете использовать любимый текстовый редактор, например GNU Emacs или Vim. С Qt работают также традиционные IDE, такие как KDevelop.

    Однако не так давно Qt Software выпустила свою кросс-платформенную IDE Qt Creator. В неё встроены все инструменты разработчика, имеется редактор с подсветкой и дополнением кода, отладчик (графический интерфейс для gdb ), а также реализована поддержка Perforce, SVN и Git.

    При работе в Qt Creator используется несколько режимов, которым соответствуют вкладки на панели слева. Для быстрого переключения между режимами можно использовать комбинации клавиш Ctrl+1, Ctrl+2 , и т.д. Основному режиму редактирования соответствует Ctrl+2 .

    Рисунок 4. Qt Creator

    Для навигации в редакторе применяется комбинация клавиш Ctrl+K . После ее нажатия нужно указать один из префиксов:

    Таблица 1. Префиксы для навигации в Qt Creator

    l Строка в текущем документе
    m Методы
    c Классы
    : Классы и методы
    ? Предметный указатель справки
    f Файлы на диске
    a Файлы во всех проектах
    p Файлы в текущем проекте

    После префикса нажмите пробел и введите соответствующую информацию. Например, для перехода на строку 93 текущего файла нужно напечатать » l 93 » (то же самое можно сделать при помощи Ctrl+L ), для перехода к документации по теме qobject_cast – «? qobject_cast» и т.д.

    В нижней части окна при этом отображается поле с автоматическим дополнением.

    Рисунок 5. Поле для навигации в Qt Creator

    Таблица 2. Комбинации клавиш для редактора Qt Creator

    Ctrl+[ Перейти к началу блока
    Ctrl+] Перейти к концу блока
    Ctrl+U Выделить блок
    Ctrl+Shift+U Снять выделение блока
    Ctrl+I Выровнять блок
    Ctrl+ Развернуть блок
    Ctrl+/ Закомментировать блок
    Ctrl+Shift+↑ Переместить строку вверх
    Ctrl+Shift+↓ Переместить строку вниз
    hift+Del SУдалить строку

    Во встроенном редакторе реализовано «умное» дополнение кода, вызываемое комбинацией клавиш Ctrl+ . База символов составляется на основе заголовочных файлов проекта из INCLUDEPATH .

    Рисунок 6. Дополнение кода в Qt Creator

    Для чтения документации в IDE предусмотрен отдельный режим справки. Чтобы получить контекстную помощь по классу или методу, просто передвиньте текстовый курсор к имени и нажмите F1 . Также полезна клавиша F2 , перемещающая к определению в заголовочных файлах.

    Чтобы переключиться из режима справки или отладки в основной режим редактирования, нажмите Esc . В режиме редактирования Esc переводит фокус из дополнительных окон (например, вывода компиляции или контекстной справки) на редактор. Если нажать Esc еще раз, то дополнительные окна закрываются.

    Как и qmake , Qt Creator использует файлы в формате .pro , поэтому в IDE легко импортируются старые проекты, созданные вручную. Также доступен мастер, при помощи которого можно создать заготовку нового проекта.

    Сейчас Qt Creator активно разрабатывается, но если вам нужна классическая IDE для Qt, работающая на различных платформах, то это лучший вариант.

    4. Стиль Qt

    В Qt используется CamelCasing: имена классов выглядят как MyClassName , а имена методов – как myMethodName .

    При этом имена всех классов Qt начинаются с Q , например QObject, QList или QFont .

    Большинству классов соответствуют заголовочные файлы с тем же именем (без расширения .h ), т.е. нужно использовать:

    Поэтому в дальнейшем мы не будем отдельно оговаривать, где объявлен тот или иной класс.

    Методы для получения и установки свойств (getter и setter) именуются следующим образом: свойство fooBar можно получить при помощи метода fooBar() и установить при помощи setFooBar() .

    При разработке собственных приложений на Qt стоит придерживаться этого стиля.

    5. Объектная модель

    Для эффективной работы с классами на стадии выполнения в Qt используется специальная объектная модель, расширяющая модель C++. В частности, добавляются следующие возможности:

    • древовидные иерархии объектов;
    • аналог dynamic_cast для библиотеки, не использующий RTTI;
    • взаимодействие объектов через сигналы и слоты;
    • свойства объектов.

    Многие объекты определяются значением сразу нескольких свойств, внутренними состояниями и связями с другими объектами. Они представляют собой индивидуальные сущности, и для них не имеет смысла операция буквального копирования, а также разделение данных в памяти. В Qt эти объекты наследуют свойства QObject .

    В тех случаях, когда объект требовалось бы рассматривать не как сущность, а как значение (например, при хранении в контейнере) – используются указатели. Иногда указатель на объект, наследуемый от QObject , называют просто объектом.

    Инструментарий спроектирован так, что для QObject и всех его потомков конструктор копирования и оператор присваивания недоступны – они объявлены в разделе private через макрос Q_DISABLE_COPY() :

    Будьте внимательны и не используйте конструкцию

    Foo bar = Foo (baz);

    Другие объекты (например, контейнеры и строки) полностью определяются представляемыми данными, поэтому в соответствующих классах имеются операция присваивания и конструктор копирования. Кроме того, объекты, представляющие одинаковые данные, могут прозрачно для программиста разделять их в памяти.

    Рисунок 7. Некоторые классы Qt.

    5.1. Система метаобъектов

    Часть расширений реализована стандартными методами C++, однако Qt использует и более сложные синтаксические расширения, поэтому он использует автоматическую генерацию кода.

    Для этого в C++ реализован механизм шаблонов, но он не предоставляет всех необходимых Qt возможностей, плохо совместим с динамической объектной моделью и в полной мере не поддерживается всеми версиями компиляторов.

    В сложных ситуациях Qt использует свой компилятор метаобъектов moc , преобразующий код с расширениями в стандартный код C++. Для обозначения того, что класс использует метаобъектные возможности (и, соответственно, должен обрабатываться moc ), в разделе private нужно указать макрос Q_OBJECT .

    Если вы встречаете странные ошибки компиляции, сообщающие, что у класса не определен конструктор, либо у него нет таблицы виртуальных функций ( vtbl ), скорее всего вы забыли код, генерируемый moc. Обычно это происходит, если не указан макрос Q_OBJECT .

    Во избежание ошибок Q_OBJECT лучше использовать во всех классах, наследуемых от QObject (косвенно либо напрямую).

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

    В числе прочих, метаобъектный код добавляет метод

    virtual const QMetaObject* QObject::metaObject() const;

    который возвращает указатель на метаобъект объекта.

    На системе метаобъектов основаны сигналы, слоты и свойства.

    При наследовании от QObject помните об ограничениях, налагаемых moc :

    1. При множественном наследовании потомком QObject должен быть первый и только первый наследуемый класс:
    2. Виртуальное наследование с QObject не поддерживается.

    5.2. qobject_cast

    Для динамического приведения QObject используется функция

    T qobject_cast (QObject *object);

    Она работает как стандартная операция dynamic_cast в C++, но не требует поддержки со стороны системы динамической идентификации типов (RTTI).

    Пусть у нас имеется класс MyClass1 , наследующий от QObject и MyClass2 , наследующий от MyClass1 :

    Динамическое приведение иллюстрирует следующий код:

    Эти операции сработают корректно на стадии выполнения.

    Как и в случае с dynamic_cast , результат приведения можно проверить:

    Система метаобъектов позволяет также проверить, наследует ли a класс MyClass1 :

    Однако предпочтителен предыдущий вариант с qobject_cast .

    5.3. Деревья объектов

    Объекты классов, наследующих от QObject , могут быть организованы в древовидную структуру. При удалении объекта Qt удаляет его дочерние объекты, которые в свою очередь удаляют свои дочерние объекты, и т.д. Иными словами, удаление объекта приводит к удалению всего поддерева, корнем которого он является.

    Пусть у нас имеются классы ClassA и ClassB :

    Листинг 2.1. Объявление My >
    Листинг 2.2. Определение методов My >

    Здесь родительский объект устанавливается в конструкторе QObject :

    QObject::QObject (QObject *parent = 0);

    Его можно установить в последующем при помощи метода setParent() и получить при помощи parent() :

    void QObject::setParent (QObject *parent);
    QObject* QObject::parent() const;

    Если создать в стеке по одному из объектов A и B, то сначала будет создан A, потом B. В соответствии со стандартом C++, удаление происходит в обратном порядке – сначала B, затем A:

    Листинг 2.3. Создание экземпляров My >

    Если создать B в куче и назначить его дочерним объектом для A, то вместе с A автоматически удалится B:

    Листинг 2.4. Создание экземпляра A класса My >

    Аналогично для более сложных деревьев:

    Рисунок 8. Пример многоуровневого дерева объектов
    Листинг 2.5. Многоуровневое дерево объектов с корнем в стеке

    После удаления A удалится всё дерево.

    Таким образом, программист должен создавать объекты в куче и задавать соответствующие иерархии, а заботу об управлении памятью Qt берет на себя.

    Если объект и его дочерние объекты созданы в стеке, то подобный порядок удаления может привести к ошибкам.

    Здесь при выходе из области действия сначала будет удален объект A, так как он был создан последним. При этом Qt удалит и его дочерний объект B. Но потом будет сделана попытка удаления B, что приведет к ошибке.

    В другом случае проблем не будет, потому что при вызове деструктора QObject объект удаляет себя из списка дочерних объектов родительского объекта:

    Вообще говоря, дочерние объекты должны размещаться в куче.

    У каждого QObject есть свойство objectName , для доступа к которому используются методы

    По умолчанию objectName – пустая строка. Через это свойство объектам в дереве можно присвоить имена для последующего поиска.

    – возвращает список дочерних объектов.

    – возвращает дочерний объект с именем name, который можно привести к типу T, либо 0, если такой объект не найден. Без аргумента name возвращает все дочерние объекты. Поиск осуществляется рекурсивно.

    QList QObject::findChildren (const QString& name = QString()) const;

    – возвращает все дочерние объекты с именем name, которые можно привести к типу T, либо пустой список, если таких объектов не найдено. Без аргумента name возвращает все дочерние объекты. Поиск осуществляется рекурсивно.

    QList QObject::findChildren (const QRegExp& regExp) const;

    – аналогично, но с поиском по регулярному выражению regExp.

    – выводит отладочную информацию о дереве объектов с данным корнем.

    5.4. Сигналы и слоты

    При создании графических пользовательских интерфейсов взаимодействие объектов часто осуществляется через обратные вызовы, т.е. передачу кода для последующего выполнения (в виде указателей на функции, функторов, и т.д.). Также популярна концепция событий и обработчиков, в которой обработчик действует как перехватчик события определенного объекта.

    В Qt вводится концепция сигналов и слотов.

    Сигнал отправляется при вызове соответствующего ему метода. Программисту при этом нужно только указать прототип метода в разделе signals .

    Слот является методом, исполняемым при получении сигнала. Слоты могут объявляться в разделе pulic slots, protected slots или private slots . При этом уровень защиты влияет лишь на возможность вызова слотов в качестве обычных методов, но не на возможность подключения сигналов к слотам.

    Модель сигналов и слотов отличается от модели событий и обработчиков тем, что слот может подключаться к любому числу сигналов, а сигнал может подключаться к любому числу слотов. При отправке сигнала будут вызваны все подключенные к нему слоты (порядок вызовов не определен).

    5.4.1. Объявление сигналов и слотов, отправка сигналов

    В качестве типичного примера слота рассмотрим метод получения свойства (getter). Методу установки свойства (setter) при этом будет соответствовать сигнал.

    Листинг 3.1. Класс My >

    Обратите внимание на макрос Q_OBJECT , сигнализирующий Qt о том, что используются возможности системы метаобъектов.

    Листинг 3.2. Реализация методов класса My >

    Ключевое слово emit отвечает за отправку сигнала.

    Для сигнала задается только прототип, причем сигнал не может возвращать значение (т.е., указывается void ). За реализацию отвечает компилятор метаобъектов, он же преобразует расширенный синтаксис с ключевыми словами signals, slots, emit в стандартный код C++.

    На самом деле, ключевые слова можно заменить на макросы Q_SIGNALS, Q_SLOTS и Q_EMIT . Это полезно, если вы используете сторонние библиотеки, в которых уже используются слова signals, slots или emit .

    Обработка ключевых слов отключается флагом no_keywords . В файл проекта qmake (.pro) добавьте

    Вы можете посмотреть на результат работы компилятора метаобъектов в файле moc_slots.cpp , который генерируется на основе slots.h и компилируется вместе с остальными .cpp .

    5.4.2. Подключение сигнала к слоту

    Листинг 3.3. Подключение сигнала vo >

    Здесь при помощи QObject::connect сигнал объекта a соединяется со слотом объекта b (передаются указатели на QObject ). Макросы SIGNAL и SLOT формируют строковые сигнатуры методов. Их аргументы должны содержать прототипы без указания имен переменных, т.е. SIGNAL(valueChanged(int x)) – недопустимый вариант.

    Сигнатуры используются для сверки типов: сигнатура сигнала должна соответствовать сигнатуре слота. При этом у слота сигнатура может быть короче, если дополнительные аргументы игнорируются.

    Другой вариант вызова QObject::connect :

    Таким образом, здесь вызов MyClass::setValue для a задействует MyClass::setValue для b .

    Обратите внимание на строку if (x_ == x) return; . Она нужна, чтобы избежать проблем при циклических соединениях. Например, следующий код сработает:

    Листинг 3.4. Циклическое соединение сигналов vo >

    QObject::connect возвращает true , если соединение успешно установлено, и false в противном случае – например, когда сигнал или слот не обнаружен, либо их сигнатуры несовместимы.

    Если добавить при помощи QObject::connect одинаковые соединения, то слот будет вызываться несколько раз.

    5.4.3. Отключение

    Для отключения сигнала от слота используется QObject::disconnect :

    При успешном отключении возвращается true .

    Если вместо сигнала (SIGNAL(. )) указать 0, то данный получатель сигнала ( b ) и слот отключаются от любого сигнала:

    Если 0 указать вместо получателя сигнала ( b ) и слота (SLOT(. )) , то отключено будет всё, что подключено к данному сигналу:

    Если 0 указать вместо слота (SLOT(. )) , то отключено будет всё, что подключено к данному получателю сигнала ( b ):

    Получаем следующие варианты вызова QObject::disconnect :

    При удалении одного из объектов соединения Qt автоматически удаляет само соединение.

    5.4.4. Ограничения

    У компилятора метаобъектов имеется ряд ограничений, которые распространяются и на работу с сигналами и слотами.

      moc не обрабатывает шаблоны и макросы, поэтому шаблоны классов не могут определять сигналы и слоты, а при объявлении сигналов и слотов нельзя использовать макросы (в том числе при указании параметров).

    Макросы нельзя использовать в любых участках кода, которые должны обрабатываться moc . В частности, через них нельзя указать базовый класс.

    Однако некоторые возможности препроцессора использовать можно. Доступны простые условные конструкции (с директивами #if, #ifdef, #ifndef, #else, #elif, #endif , а также специальным оператором defined ). Для создания объявлений у moc имеется опция командной строки -D . Утилита qmake передает moc все объявления, перечисленные в параметре проекта DEFINES .

    Например, moc правильно обработает

    также будет обработан, только если вызвать moc -DFOO , либо если до него имеется строка #define FOO .


    Типы должны быть указаны полностью, так как QObject::connect() сравнивает их буквально. В частности, если внутри класса Foo определяется перечисление Bar , то в аргументах сигнала нужно указывать Foo::Bar :

    В качестве параметров сигналов и слотов нельзя использовать указатели на функции. Например,

    не является допустимым аргументом. Можно использовать typedef:

    Обычно вместо указателей лучше применять наследование и виртуальные функции.

  • Вложенные классы не могут содержать сигналы и слоты.
  • Сигналы и слоты, возвращающие ссылки, обрабатываются таким образом, как если бы они возвращали void .
  • В разделах signals и slots могут объявляться только сигналы и слоты.
  • 5.5. Свойства

    Класс, наследующий QObject , может содержать объявление свойства при помощи макроса Q_PROPERTY() :

    Q_PROPERTY( type name

    Обязательные параметры макроса:

    • type – тип свойства;
    • name – имя свойства;
    • getFunction – const-метод для считывания значения; возвращаемый тип должен быть type, type* либо type&.

    Не обязательные параметры макроса:

    • setFunction – метод для установки значения свойства, должен возвращать void и принимать только один аргумент типа type, type*, либо type&;
    • resetFunction – метод для установки значения свойства по умолчанию, зависящего от контекста, должен не иметь аргументов и возвращать void ;

    Методы могут быть виртуальными либо унаследованными от базового класса. При множественном наследовании они должны принадлежать первому классу в списке.

    Для не обязательных атрибутов DESIGNABLE, SCRIPTABLE, STORED, USER допускается указание булевых значений:

    • DESIGNABLE – показывать ли свойство в Qt Designer и подобных графических программах. По умолчанию true , также можно указать булев метод.
    • SCRIPTABLE – должно ли свойство быть видимым скриптовому движку. По умолчанию true , также можно указать булев метод.
    • STORED – должно ли свойство сохраняться при сохранении состояния объекта либо оно вычисляется через другие свойства. По умолчанию true .
    • USER — редактируется ли свойство пользователем. Обычно у классов, соответствующих элементам управления, бывает одно такое свойство. По умолчанию false .

    Например, QWidget объявляет, в числе прочих, следующие свойства:

    Q_PROPERTY (QSize minimumSize READ minimumSize WRITE setMinimumSize) Q_PROPERTY(int minimumWidth READ minimumWidth WRITE setMinimumWidth STORED false DESIGNABLE false) Q_PROPERTY(int minimumHeight READ minimumHeight WRITE setMinimumHeight STORED false DESIGNABLE false)

    Свойство minimumSize имеет тип QSize и может быть получено при помощи QSize minimumSize() const и установлено при помощи void setMinimumSize ( const QSize& ). minimumWidth и minimumHeight вычисляются через minimumSize , поэтому для них указано STORED false .

    Пример свойства с атрибутом USER – text в QLineEdit :

    Для считывания и записи свойства используются методы:

    property() возвращает значение свойства либо неправильный вариант QVariant , если такого свойства нет.

    setProperty() возвращает true , если у объекта есть указанное свойство с типом, совместимым с переданным значением. В противном случае возвращается false .

    Если в классе нет указанного свойства, то добавляется динамическое свойство объекта. Перечень динамических свойств можно получить при помощи

    Рассмотрим пример использования свойств. Пусть класс MyClass имеет строковое свойство text (типа QString ):

    Листинг 4.1. Объявление класса My >
    Листинг 4.2. Определение методов класса My >

    Работа со свойством:

    Листинг 4.3. Работа со свойством text объекта My >

    Программа должна вывести на экран следующее:

    Разумеется, безопаснее и быстрее вызывать методы конкретного класса для считывания и записи свойств. property() и setProperty() нужны в том случае, когда о классе ничего не известно кроме имен и типов свойств.

    Если для класса не известен даже перечень свойств и методов, можно использовать метаобъект.

    5.6. Работа с метаобъектами

    Метаобъект возвращается методом

    С его помощью можно динамически получить информацию о классе, как, например, в Java Reflecion API (EN).

    5.6.1. Основная информация

    Имя класса возвращает

    const char * QMetaObject::className() const;

    Указатель на метаобъект базового класса –

    const QMetaObject* superClass() const;

    5.6.2. Методы

    Через систему метаобъектов доступны только те методы и конструкторы, перед объявлениями которых указан макрос Q_INVOKABLE :

    Для доступа к методам (в том числе сигналам и слотам) используйте

    Методы и свойства класса проиндексированы. Доступ к методу по индексу осуществляется через QMetaObject::method() .

    Общее число методов, с учетом наследованных, возвращает QMetaObject::methodCount() . Смещение методов класса возвращается QMetaObject::methodOffset() , оно показывает, с какого индекса начинаются методы данного класса. Смещение увеличивается при наследовании и показывает число методов базовых классов.

    Пример прохода по методам:

    Если бы мы начали с индекса 0, то получили бы методы всех базовых классов, в том числе QObject :

    Методы, начинающиеся с _q_ , используются внутри Qt и не являются частью API.

    Конструкторы указываются отдельно:

    Например, получим перечень конструкторов QObject :

    Листинг 5. Вывод конструкторов QObject через систему метаобъектов

    Индекс метода, сигнала, слота или конструктора можно получить по его сигнатуре:

    Для конструкторов, методов или сигналов ожидаются нормализованные сигнатуры. Их можно получить при помощи статического метода

    Это текстовое приведение к каноническому виду, используемое, в частности, при проверке совместимости сигнала и слота.

    5.6.3. Свойства

    Аналогично можно работать со свойствами.

    (Если просмотреть все свойства, включая наследованные, то вы увидите, по меньшей мере, objectName из QObject .)

    Индекс свойства можно получить по его имени:

    5.6.4. Перечисления

    Перечисления регистрируются в классе при помощи макроса Q_ENUMS() .

    Перечисление, значения которого можно комбинировать при помощи побитового ИЛИ, называется флагом и должно регистрироваться при помощи Q_FLAGS() .

    Листинг 6.1. Класс My >

    Флаги используются следующим образом:

    Динамическая работа с перечислениями:

    Листинг 6.2. Вывод перечислений и флагов My >

    Индекс перечисления можно получить по его имени:

    5.6.5. CLASSINFO

    При помощи макроса Q_CLASSINFO() к метаобъекту можно добавлять пары имя–значение. Например,

    Листинг 7.1. Класс My >

    Эти пары наследуются, и их можно получить из метаобъекта по той же схеме:

    Для примера выше:

    Листинг 7.2. Вывод >

    Индекс CLASSINFO можно получить по его имени:

    5.6.6. Вызов конструкторов и методов

    Передача аргументов осуществляется через объекты QGenericArgument и QGenericReturnArgument . Они создаются макросами Q_ARG и Q_RETURN_ARG .

    Для создания нового экземпляра класса используется метод метаобъекта newInstance() , которому можно передать до 10 аргументов.

    В случае ошибки возвращается 0.

    Для вызова метода используется invokeMethod() :

    • obj – указатель на объект;
    • member – имя метода;
    • type – тип вызова:
      • Qt::DirectConnection – незамедлительно,
      • Qt::QueuedConnection – при начале выполнения QCoreApplication::exec() ,
      • Qt::AutoConnection – синхронно, если объект находится в том же потоке, и асинхронно в противном случае;
    • ret – возвращаемое значение;

    далее следует до 10 аргументов.

    При асинхронном вызове значение не может быть вычислено.

    Имеются перегруженные версии invokeMethod() . Если вы не укажете тип вызова, то будет использоваться Qt::AutoConnection . Если вы не укажете возвращаемое значение, то оно будет проигнорировано.

    Те же возможности предоставляет класс QMetaMethod :

    Точно так же, тип соединения и/или возвращаемое значение можно не указывать.

    Асинхронный вызов используется в том случае, когда вычисления занимают слишком много времени, поэтому их результат не ожидается в точке вызова. Подобные вычисления обычно помещают в отдельный поток, поэтому по умолчанию ( Qt::AutoConnection ) методы объектов из внешних потоков вызываются асинхронно.

    Рассмотрим следующий класс:

    Листинг 8.1. Класс My >

    Обращение к конструктору и методам:

    Листинг 8.2. Вызов конструкторов и методов класса My >

    text() и setText() вызываются таким образом лишь в качестве простого примера работы с QMetaObject::invokeMethod() . Как вы уже знаете, эти два метода должны быть связаны со свойством.

    Также обратите внимание, что text() возвращает QString , но не const QString& . Иначе бы система метаобъектов считала, что text() возвращает void .

    Заключение

    Для эффективной работы с классами на стадии выполнения Qt использует специальную объектную модель, в которой при помощи наследования от QObject и генерирования кода компилятором метаобъектов реализованы:

    • иерархии объектов;
    • специальный аналог dynamic_cast , не зависящий от RTTI;
    • система сигналов и слотов;
    • система свойств объектов;
    • динамическая работа с классами.

    В следующей статье мы рассмотрим типы, варианты, ссылки и разделение данных.

    Ресурсы для скачивания

    Похожие темы

    • Исходный код с примерами (EN).
    • Qt Software (EN).
    • Документация по Qt (EN).
    • Qt Centre (EN).
    • Информационный бюллетень «Qt Quarterly» (EN).
    • Списки рассылки Qt (EN).
    • Jasmin Blanchette, Mark Summerfield. C++ GUI Programming with Qt 4 (2nd Edition) (EN). Prentice Hall: 2006. – 752 pp.
    • Daniel Molkentin. The Book of Qt 4: The Art of Building Qt Applications (EN). No Starch Press: 2007. – 440 pp.
    • J. Thelin. Foundations of Qt Development (EN). Apress: 2007. – 528 pp.
    • Bjarne Stroustrup. The C++ Programming Language (Special Edition) (EN). Addison-Wesley: 2000 – 1040 pp.

    Комментарии

    Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

    Сложение двух чисел в Qt 5.7.0 на C++ (Qt Quick Controls 2)

    В статье описывается создание приложения QML через Qt Quick Controls 2 с выполнением кода на С++.

    01.08.2020 14 комментариев 8 756 просмотров

    В статье описывается создание приложения QML через Qt Quick Controls 2 (раньше назывались Qt Labs Controls) с выполнением кода на С++.

    В качестве среды для разработки используется Qt 5.7.0 для Windows 64 bit под компилятор Visual Studio 2015.

    Статья из цикла «Сложение двух чисел». Для меня минимальное освоение любой системы программирования начинается с возможности создания такой программы. Если можно написать приложение, в которой пользователь может ввести два числа, считать их, провести с ними какие-то действия, а потом вывести результат, то, значит, базовое владение имеется. И много задач именно из области программирования, алгоритмики можно будет решать, зная, как в конкретной системе программирования запрограммировать такую программу.

    Содержание

    Подготовка

    Создадим Qt Quick приложение.

    И переведите разработку приложения в режим Release .

    По умолчанию создается в болванке три qml файла. Удалим два из них — они нам пока не нужны.

    Qt — кросс-платформенный инструментарий разработки ПО на языке программирования C++ от компании Qt Development Frameworks (ранее известна как Qt Software, Trolltech)

    Читайте также:

    1. Brief performance history of electric drive development
    2. Development of Meaning
    3. Features and tendency of development of modern electric drive
    4. MODERN ELECTRIC DRIVE, ITS FEATURES AND TENDENCIES OF DEVELOPMENT
    5. MODERN TRENDS OF THE WORLD ECONOMY AND INTERNATIONAL ECONOMIC RELATIONS DEVELOPMENT
    6. Recent developments
    7. THE WORLD ECONOMY AND INTERNATIONAL ECONOMIC RELATIONS: THE CONCEPT, ESSENCE, FORMS AND PARTICULARITIES OF THEIR DEVELOPMENT
    8. V- образная модель ЖЦ разработки ИС
    9. Алгоритмизация и основы программирования
    10. Алгоритмические (процедурные) языки программирования
    11. Алгоритмы и языки программирования

    Лекция и Лабораторная работа

    По курсу: Операционные системы

    На тему: Среда программирования Qt

    Студенты группы А-06-09

    Содержание:

    8.Работа с Qt Creator

    10.Задание на лабораторную работу

    Введение

    Есть также «привязки» ко многим другим языкам программирования: Python — PyQt, Ruby — QtRuby, Java — Qt Jambi, PHP — PHP-Qt и другие.

    Позволяет запускать написанное с его помощью ПО в большинстве современных операционных систем путём простой компиляции программы для каждой ОС без изменения исходного кода. Включает в себя все основные классы, которые могут потребоваться при разработке прикладного программного обеспечения, начиная от элементов графического интерфейса и заканчивая классами для работы с сетью, базами данных и XML. Qt является полностью объектно-ориентированным, легко расширяемым и поддерживающим технику компонентного программирования.

    Начиная с версии 4.5 Qt распространяется с различными лицензиями. Это означает, что если вы собираетесь создавать коммерческие приложения, то должны приеобрести коммерческую лицензию Qt; если же создаётся программа с открытым исходным кодом, то можно использовать версию с лицензией GPL.

    История

    Средства разработки Qt впервые стали известны общественности в мае 1995 года. Первоначально Qt разрабатывалось Хаарвардом Нордом и Айриком Чеймб-Ингом.

    В 1991 году Хаарвард начал писать классы, которые фактически образовали Qt, причём проектные решения принимались совместно с Айриком.

    В следующем году Айрику пришла идея «сигналов и слотов» — простой, но мощной парадигмы программирования GUI, которая в настоящее время заимствована некоторыми другими инструментами.

    К 1993 году Хаарвард и Айрик разработали первое графическое ядро Qt и могли создавать собственные виджеты.

    Неинтересные заметки: Буква «Q» была выбрана в качестве префикса классов, поскольку эта буква имела красивое начертание в шрифте Emacs, которым пользовался Хаарвард. Была добавлена буква «t», означающая «toolkit»(инструментарий).

    Развитие

    В апреле 1995 года — норвежская компания «Metis» заключила с ними контракт на разработку программного обеспечения на основе Qt.

    26 мая 1995 года — первая публичная версия Qt. Qt можно было использовать в разработках как Windows, так и Unix, причём программный интерфейс был одинаковый на обеих платформах.

    С 1996 по 2001 год – развитие до версии Qt3. Qt теперь работала в системах Windows, Mac Os X, Unix.


    Лето 2005 года — выпущена Qt 4.0. Имея около 500 классов и более 9000 функций, Qt 4 оказалась больше и богаче любой предыдущей версии; она была разбита на несколько библиотек, чтобы разработчики могли использовать только нужные им части Qt.

    На сегодняшный день версия Qt4.8

    Версия Qt 4 представляет собой большой шаг вперёд по сравнению с предыдущими версиями; она содержит полностью новый набор эффективных и простых в применении классов-контейнеров, усовершенствованную функциональность архитекторы модель/представление, быстрый и гибкий фреймфорк графики 2D и мощные классы для просмотра и редактирования текста в кодировке Unicode, не говоря уже о тысячах небольших улучшений по всему спектру классов Qt.

    Qt 4 является первой версией Qt, доступной на всех поддерживаемых платформах как для коммерческой разработки, так и для разработки с открытым исходным кодом.

    Область применения

    Возможность создавать desktop-приложения для Windows, Linux, Mac OS X (как консольные, так и с оконным графическим интерфейсом). В последние несколько лет наблюдается тенденция увеличения количества выпускаемых мобильных устройств. В следствии чего Qt портировали на мобильные платформы: Symbian, Maemo, MeeGo. Также известно об удачном опыте портрования Qt Lighthouse на платформу Android.

    Общие сведения

    Позволяет запускать написанное с его помощью ПО в большинстве современных операционных систем путём простой компиляции программы для каждой ОС без изменения исходного кода.

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

    Qt является полностью объектно-ориентированным, легко расширяемым и поддерживающим технику компонентного программирования.

    Существуют версии библиотеки для Microsoft Windows, систем класса UNIX с графической подсистемой X11, iOS, Android, Mac OS X, Microsoft Windows CE, QNX[7], встраиваемых Linux-систем и платформы S60. В данный момент рассматривается возможность внедрения поддержки Qt в Windows Phone. Также идёт портирование на Haiku.

    Отличительная особенность Qt от других библиотек — использование Meta Object Compiler (MOC) — предварительной системы обработки исходного кода (в общем-то, Qt — это библиотека не для чистого C++, а для его особого наречия, с которого и «переводит» MOC для последующей компиляции любым стандартным C++ компилятором). MOC позволяет во много раз увеличить мощь библиотек, вводя такие понятия, как слоты и сигналы. Кроме того, это позволяет сделать код более лаконичным. Утилита MOC ищет в заголовочных файлах на C++ описания классов, содержащие макрос Q_OBJECT, и создаёт дополнительный исходный файл на C++, содержащий метаобъектный код.

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

    Qt комплектуется визуальной средой разработки графического интерфейса «Qt Designer», позволяющей создавать диалоги и формы в режиме WYSIWYG.

    В поставке Qt есть «Qt Linguist» — графическая утилита, позволяющая упростить локализацию и перевод программы на многие языки; и «Qt Assistant» — справочная система Qt, упрощающая работу с документацией по библиотеке, а также позволяющая создавать кросс-платформенную справку для разрабатываемого на основе Qt ПО. Начиная с версии 4.5.0 в комплект Qt включена среда разработки «Qt Creator», которая включает в себя редактор кода, справку, графические средства «Qt Designer» и возможность отладки приложений. «Qt Creator» может использовать GCC или Microsoft VC++ в качестве компилятора и GDB в качестве отладчика. Для Windows версий библиотека комплектуется компилятором, заголовочными и объектными файлами MinGW.

    Компоненты (выделим парочку)

    Библиотека разделена на несколько модулей, для четвёртой версии библиотеки это:

    QtCore — классы ядра библиотеки, используемые другими модулями;

    QtGui — компоненты графического интерфейса;

    QtNetwork — набор классов для сетевого программирования. Поддержка различных высокоуровневых протоколов может меняться от версии к версии. В версии 4.2.x присутствуют классы для работы с протоколами FTP и HTTP. Для работы с протоколами TCP/IP предназначены такие классы, как QTcpServer, QTcpSocket для TCP и QUdpSocket для UDP;

    QtOpenGL — набор классов для работы с OpenGL;

    QtSql — набор классов для работы с базами данных с использованием языка структурированных запросов SQL. Основные классы данного модуля в версии 4.2.х: QSqlDatabase — класс для предоставления соединения с базой, для работы с какой-нибудь конкретной базой данных требует объект, унаследованный от класса QSqlDriver — абстрактного класса, который реализуется для конкретной базы данных и может требовать для компиляции SDK базы данных. Например, для сборки драйвера под базу данных FireBird/InterBase требует .h файлы и библиотеки статической линковки, входящие в комплект поставки данной БД;

    QtScript — классы для работы с Qt Scripts;

    QtSvg — классы для отображения и работы с данными Scalable Vector Graphics (SVG);

    QtXml — модуль для работы с XML, поддерживается SAX и DOM модели работы;

    QtDesigner — классы создания расширений QtDesigner’а для своих собственных виджетов;

    QtUiTools — классы для обработки в приложении форм Qt Designer;

    QtAssistant — справочная система;

    Qt3Support — модуль с классами, необходимыми для совместимости с библиотекой Qt версии 3.х.х;

    QtTest — модуль для работы с UNIT тестами;

    QtWebKit — модуль WebKit, интегрированный в Qt и доступный через её классы;

    QtXmlPatterns — модуль для поддержки XQuery 1.0 и XPath 2.0;

    Phonon — модуль для поддержки воспроизведения и записи видео и аудио, как локально, так и с устройств и по сети;

    QtCLucene — модуль для поддержки полнотекстового поиска, применяется в новой версии Assistant в Qt 4.4;

    ActiveQt — модуль для работы с ActiveX и COM технологиями для Qt-разработчиков под Windows.

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

    Библиотека использует собственный формат проекта, именуемый .pro файлом, в котором собрана информация о том, какие файлы будут скомпилированы, по каким путям искать заголовочные файлы и много другой информации.

    Впоследствии при помощи утилиты qmake из них получаются makefile для make-утилиты компилятора. Также есть возможность работы при помощи интеграторов с Microsoft Visual Studio 2003/2005/2008/2010. Совсем недавно стала доступна интеграция в Eclipse для версии библиотеки 4.х.х.

    Разработчики на Java могут использовать Qt с помощью фреймворка Qt Jambi от того же производителя (официально с 2009 года Qt Software прекратила разработку этого фреймворка).

    Одним из весомых преимуществ проекта Qt является наличие качественной документаци. Статьи документации снабжены большим количеством примеров. Исходный код самой библиотеки хорошо форматирован, подробно комментирован и легко читается, что также упрощает изучение Qt.

    Среда разработки

    Qt Creator — кроссплатформенная свободная IDE для разработки на С, С++ и QML. Разработана Trolltech (Nokia) для работы с фреймворком Qt. Включает в себя графический интерфейс отладчика и визуальные средства разработки интерфейса как с использованием QtWidgets, так и QML. Поддерживаемые компиляторы: Gcc, Clang, MinGW, MSVC, Linux ICC, GCCE, RVCT, WINSCW.

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

    Работа в Qt Creator

    В Qt Creator есть удобный «мастер» для создания новых проектов, форм, файлов с классами и так далее. Хотя вместо создания ui-файла для главного окна можно было бы вставлять в проект какой-нибудь простой код, не касаясь вотчины визуального программирования. После создания или открытия проекта перед нами предстает сама среда разработки. Поначалу она выглядит непривычно. Например, нет знаменитых табов (вкладок с корешками). Вернее, они есть для всего кроме файлов редактора. Сами же файлы доступны из двух списков: файлов проекта (по умолчанию на панели слева) и уже открытых файлов (в верхней строке панели редактора). Почему же принято решение отказаться от вкладок? Думаю, что ради экономии места на экране.

    Еще один непривычный момент довольно относителен, поскольку интерфейс «без диалогов» давно взят на вооружение некоторыми другими программами (например, редактором TEA). В Qt Creator для поиска и замены по тексту появляются поля ввода, при наборе текста в которых найденные совпадения сразу подсвечиваются в редакторе. Для поиска дальше есть F3, а для замены — отдельное поле ввода. Рядом расположены и опции. Благодаря всему этому подобные операции проводятся быстро и удобно. То же касается информационных и отладочных панелей: никакой модальности, лишних окон, перекрывающих основное, и прочих прелестей былого подхода к архитектуре интерфейса. Всё в одном главном окне!

    В Qt Creator позаботились и о редакторе кода. Подсветкой синтаксиса нынче мало кого можно удивить, поэтому сразу перейдем к другим полезным возможностям. Например, есть «полный парсер кода» — это возможность редактора проверять код на правильность с точки зрения языка программирования. Когда вы набираете код, то еще до компиляции видите, где допустили синтаксическую ошибку. В большинстве случаев срабатывает, хотя бывают и исключения. Замечательно работает автоматическое дополнение: набрали имя экземпляра класса, поставили точку или «->» — и получаете выпадающий список с членами класса. Есть свёртывание блоков кода — так называемый «фолдинг». Впрочем, я считаю, что код более нагляден без него, поэтому никогда такой возможностью не пользуюсь.

    Хорошо сделано перемещение по коду — причем без внешнего ctags. Достаточно поставить курсор на имя функции или переменной и нажать F2, после чего редактор переносит в место объявления. Shift-F2 — переключает между объявлением и кодом, а F4 — просто переключает заголовок и cpp-файл. Если поднести указатель мыши к имени вызываемой в коде функции, то появится подсказка по ее параметрам.

    Справочная система работает следующим образом. Допустим, у вас в коде где-то есть переменная типа QMenu. Если поставить на нее курсор и нажать F1, возникает справочная панель с описанием класса QMenu. Также в главном окне существует вкладка Help, где доступна вся документации по Qt.

    Итак, большую часть времени вы будете проводить на вкладке редактора. Не совсем понятно, для чего в настройках Qt Creator есть целых пять разделов как бы для разных редакторов — по умолчанию, для скриптов, для С++, для проектов и Perforce (коммерческая система контроля над версиями). Настройки редактора С++ — это и есть настройки редактора кода вашей Qt-программы. Замечу, что в самых свежих «снэпшотах» Qt Creator настройки шрифта всё же упорядочены в единственный раздел, чего и следовало ожидать.

    Полезно заняться настройкой подсветки и шрифтов, поскольку по умолчанию работать не очень удобно. Во-первых, размер шрифта слишком мелкий, а во-вторых, блоки кода, заключенные в #ifdef / #endif, трактуются парсером как «disabled code» (выражение из настроек Qt Creator) и раскрашиваются серым цветом — разбирать написанное не очень удобно. Если вам не нравится «фолдинг», там же в настройках редактора отключите Display Folding Markers.

    На полях редактора можно ставить закладки и точки останова. Сама панель редактора может быть разделена на бесконечное множество вложенных панелей — подобно Konqueror. Таким образом на экране одновременно можно редактировать либо несколько файлов, либо один и тот же документ, но в разных местах. Для этого надо сначала разделить панель редактора (например, через Window — Split Top/Bottom), а затем выбрать пункт меню Window — Duplicate document. Такой подход иногда бывает полезнее, чем утомительные переходы по закладкам.

    Архитектура Qt Creator зиждется на плагинах. Редактор — плагин, движок закладок — плагин, панель с файлами проекта — тоже плагин, и так далее. Список установленных плагинов можно посмотреть в меню Help — About Plugins. Вероятно, в будущем можно будет устанавливать дополнительные плагины, но покамест механизма для этого я не обнаружил, равно как и самих дополнительных плагинов. Зато в самих сборках новые плагины появляются с небывалой скоростью. Только за месяц появились модули поддержки Subversion и Git. Qt Creator вообще сейчас присуща скоротечность. Пункты меню Qt Creator от версии к версии переименовываются и переносятся в другие подменю. Не говоря уже о том, что постоянно рождаются дополнительные функции.

    Уделим некоторое внимание окну настроек, которых, благо, много. Можно настраивать сочетания клавиш и, более того, импортировать / экспортировать их с помощью внешних файлов. Это удобно для переноса любимых сочетаний клавиш с машины на машину. В состав Qt Creator по умолчанию входят два таких предустановленных файла: для MS Visual C++ и Xcode. Всё, что связано с автоматическим дополнением, отступами, подсветкой синтаксиса и прочим, находится в настройках редактора — Text Editor.

    Другое интересное средство в Qt Creator — это Locator (в старых версиях — Quick find). Для того, чтобы переместить в него фокус, достаточно нажать на Ctrl-K. Выглядит как обычная строка поиска, а служит для быстрого поиска чего угодно в чём изволите. Если говорить конкретнее — ищет файлы, в файлах, классы, функции. Поддерживает символы-модификаторы для уточнения задачи поиска. Например, вы хотите найти в документации Qt описание глобального указателя qApp. Что делать? Раньше приходилось открывать документацию через браузер и искать там. Но в Qt Creator, когда всегда под рукой Locator, достаточно набрать в строке поиска ? qapp и нажать Enter. Перейти на строку под номером 100? Пожалуйста — набираете номер и снова Enter.

    И напоследок, вернемся к взаимодействию с отладчиком GDB. Qt Creator через свой графический интерфейс позволяет отлаживать не только текущий проект, но и любую внешнюю программу — конечно, если она собрана с отладочной информацией. При отладке данные различного рода отображаются в отдельных вкладках: нити, переменные, точки останова и дизассемблер. Особенно наглядно выглядит в отладчике экземпляр QStringList — видны все его элементы. Стандартный вывод самого GDB по умолчанию выключен, равно как и некоторые другие вкладки вроде сведений о содержимом регистров процессора. Если программа по какой-то причине «вылетает», то по данным в отладочной панели сразу видно, в каком именно месте кода произошел сбой.

    Пример 1

    Наша первая программа будет с графическим интерфейсом пользователя(GUI — Graphical User Interface).

    int main(int argc, char *argv[])

    QApplication app(argc, argv);

    QPushButton *newbtn = new QPushButton(QObject::tr(«OK»));

    Первые две строки — определения классов Qt.

    Эти классы относится к интерфейсу прикладного программирования (API — Application Programming Interface) библиотеки Qt. В библиотеке есть файлы с такими же названиями, описывающие данный классы.

    В строке 6 создается объект QApplication. Данный класс управляет всеми ресурсами приложения. Затем создается объект класса QPushButton(кнопка) с надписью «OK».

    Кнопка является виджетом. Строка 8 служит для связывания сигнала clicked() кнопки со слотом quit() объекта QApplication3. В строке 9 мы устанавливаем размер виджета и в строке 10 отображаем его. Строка 11 служит для передачи управления приложением Qt. В этом месте программа переходит в цикл обрабоки пользовательских и системных событий.

    Пример 2. Проверка вводимых пользователем данных

    Когда пользователю предлагается ввести какие-либо данные в текстовое поле, то довольно часто можно получить что-то абсолютно неожиданное. Пользователь может ввести числа прописью, использовать неверный десятичный разделитель или забыть указать код города в телефонном номере. Таким образом, в большинстве случаев, необходимо проверять правильность(допустимость)1 указанной информации.

    Qt содержит класс QValidator, гарантирующий корректность введенных данных. Данных класс не может быть использован напрямую. Для проверки данных придется либо воспользоваться готовыми подклассами QIntValidator, QDoubleValidator, QRegExpValidator, либо написать подкласс самим.

    В метод validate(QString & input, int & pos) передается строка для проверки и позиция курсора. Метод может возвращать следующие значения:

    QValidator::Invalid — строка недопустима.

    QValidator::Acceptable — строка допустима.

    QValidator::Intermediate — строка не может быть принята в текущем состоянии, но она может стать допустимой.

    Составим программу, которая будет проверять, является ли строка вещественным числом. Воспользуемся готовым классом QDoubleValidator:

    Составим программу, которая будет проверять, является ли строка вещественным числом. Воспользуемся готовым классом QDoubleValidator:

    lbdouble = new QLabel(tr(«Double:»));

    lbresult = new QLabel(tr(«Result:»));

    result = new QLabel;

    vld = new QDoubleValidator(-5, 2999, 5, this);

    grid->addWidget(lbdouble, 0, 0);

    grid->addWidget(doubleedit, 0, 1);

    grid->addWidget(lbresult, 1, 0); grid->addWidget(result, 1, 1);

    resize(160, 120); setLayout(grid); .

    Конструктор класса QDoubleValidator может принимать следущие параметры:

    QDoubleValidator::QDoubleValidator ( double bottom, double top, int decimals, QObject * parent )

    Диапазон вещественных чисел от bottom до top включительно. decimals — количество знаков после десятичного разделителя2.

    Используя метод setNotation(Notation) класса QDoubleValidator можно установить допустимость научной нотации:

    QDoubleValidator::StandardNotation — стандартная нотация(Например: 1,124 или -2).

    QDoubleValidator::ScientificNotation — научная нотация, т.е. число может иметь экспоненциальную часть(Например: 2,7E-3 или 3,3E+2)

    Для проверки допустимости введенных данных воспользуемся методом validate():

    QObject::connect(doubleedit, SIGNAL(textChanged (const QString &)), this, SLOT(showresult(const QString &)));

    void MainWindow::showresult(const QString &text)

    QString numtext = text;

    if (vld->val >setText(tr(«invalid»));

    if (vld->val >setText(tr(«Intermediate»));

    if (vld->val >setText(tr(«Acceptable»));

    Код программы

    int main(int argv, char **args)

    QApplication app(argv, args);

    Mainwindiw.h #ifndef MAINWINDOW_H#define MAINWINDOW_H #include class MainWindow : public QWidget< Q_OBJECT public: MainWindow(); private slots: void showresult(const QString &); private: QGridLayout *grid; QLineEdit *doubleedit; QLabel *lbdouble, *lbresult, *result; QDoubleValidator *vld;>; #endif Mainwindow.cpp #include #include «mainwindow.h» MainWindow::MainWindow()< gr )); result = new QLabel; vld = new QDoubleValidator(-5, 2999, 5, this); vld->setNotation(QDoubleValidator::ScientificNotation); doubleedit->setValidator(vld); grid->addWidget(lbdouble, 0, 0); grid->addWidget(doubleedit, 0, 1); grid->addWidget(lbresult, 1, 0); grid->addW >val >setText(tr(«invalid»)); if (vld->val >setText(tr(«Intermediate»)); if (vld->val >setText(tr(«Acceptable»));>

    Пример 3. 2D графика

    С помощью класса QPainter мы можем рисовать на любом объекте, унаследованном от класса QPaintDevice(QWidget, QPrinter, QImage, QGLFramebufferObject и др.). Можно рисовать геометрические фигуры, пиксельные карты, текст. Для начала рассмотрим классы, которые могут быть полезны при работе с QPainter.

    Классы QPoint и QPointF служат для задания положения точки в двухмерной системе координат. QPoint — для целых чисел и QPointF — для вещественных. К точкам применимы операции сложения, вычитания, умножения, деления:

    QPoint point(5, 5);

    QPoint point2(10, 10);

    Также точки можно сравнивать между собой и на равенство их координат нулю.

    QPoint point(5, 10);

    QPoint point2(5, 10);

    if (point == point2)

    Классы QSize и QSizeF служат для хранения размера. Кроме методов, аналогичных методам классов QPoint и QPointF, данные классы обладают методом scale(), позволяющим масштабировать графический объект.

    Классы QRect и QRectF служат для хранения прямоугольных областей(координат верхнего левого угла и размера):

    QRectF(QPointF point, QSizeF size);

    Классы QLine и QLineF описывают прямую линию. Классы QPolygon и QPolygonF описывают замкнутую фигуру, образованную прямыми линиями.

    C помощью класса QColor можно хранить информацию о цвете. Среда Qt поддерживает 3 цветовые модели: RGB, CMYK и HSV. Для цветовой модели RGB существует структура QRgb. Существует несколько способов задания цвета в объекте класса QColor:

    Передача параметров в конструктор

    unsigned int red = 50;

    unsigned int green = 100;

    unsigned int blue = 0;

    unsigned int alpha = 128;

    QColor mycolor(red, green, blue, alpha);

    QRgb rgb1 = (50, 100, 0);

    С помощью методов QColor::setRgb(), QColor::setRgba(), QColor::setRgbF(), QColor::setHsv(), QColor::setHsvF(), QColor::setCmyk(), QColor::setCmykF()

    mycolor.setHsv(200, 100, 50);

    Существует возможность установить цвет в одной модели и считать в другой:

    unsigned int h, s, v;

    QColor mycolor(100, 100, 100);

    Вернемся к классу QPainter. Для того, чтобы начать рисовать нам достаточно создать объект класса QPainter и передать ему указатель на объект для рисования:

    void Wnd::paintEvent(QPaintEvent *event)

    QLineF line(10.0, 80.0, 90.0, 20.0);

    void Wnd::paintEvent(QPaintEvent *event)

    QLineF line(10.0, 80.0, 90.0, 20.0);

    Метод QWidget::paintEvent() вызывается для виджетов, которые должны быть перерисованы.

    В большинстве случаев рисование производится одним объектом QPainter на нескольких объектах рисования. Для сохранения старых настроек рисования(при переходе на новый объект) можно воспользоваться методами QPainter::save() и QPainter::restore(). QPainter::save() помещает в стек установки, а QPainter::restore() — извлекает.

    Для рисования контуров фигуры необходимо передать объекту класса QPainter объект класса QPen(перо) с помощью QPainter::setPen().

    С помощью соответствующих методов можно установить стиль пера(цвет, толщину, вид концов линии).

    Для заполнения замкнутых контуров используется кисть т.е. объект класса QBrush. По аналогии с классом QPen кисть устанавливается методом QPainter::setBrush(). В него можно передать либо объект QBrush, либо один из предопределенных стилей BrushStyle:

    pnt.setBrush(QBrush(Qt::blue, Qt::VerPattern)); // голубая кисть с вертикальной штриховкой

    Класс QPainter позволяет поворачивать, масштабировать, смещать объекты, делать скос. Для этих операций имеются соответствующие методы: rotate(), scale(), translate(), sheap().

    Библиотека Qt поддерживает технику сглаживания(Anti-Aliasing, антиалиасинг):

    | следующая лекция ==>
    Основні показники ефективності використання трудових ресурсів по групам | Сигналы и слоты

    Дата добавления: 2014-01-05 ; Просмотров: 3226 ; Нарушение авторских прав? ;

    Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет

    Технология разработки визуальных кроссплатформенных приложений с использованием фреймворка Qt на примере программы “Snake”

    В современном мире, очень важно поддерживать работу приложения на разнообразных платформах. Типичным примером является программное обеспечение, предназначенное для работы в операционных системах Linux и Windows одновременно. Qt — является отличным фреймворком, который позволяет создавать визуальные, кроссплатформенные приложения.

    Актуальность кроссплатформенности в игровой индустрии успешно доказывает опыт американской компании Valve, получившая тотальную известность, выпустив крайне успешную и хорошо принятую критиками игру Half-Life.В настоящее время для разработчика крайне важно поддерживать множество операционных систем для работы приложения. Кроссплатформенность распространяется практически на каждую it-структуру, начиная от кроссплатформенных языков программирования, таких как c, c++, Pascal, заканчивая кроссплатформенными средами исполнения и пользовательскими интерфейсами. Всем известная OpenGL – открытая графическая библиотека, определяющая платформо-независимый программный интерфейс для написания приложений, использующих двумерную и трёхмерную компьютерную графику, которая также используется в данном проекте, наглядный пример успеха платформонезависимого продукта. Qt – кроссплатформенный инструментарий разработки ПО на языке программирования C++, именно он станет нашим главным «другом» на момент написания проекта, так и в дальнейшей перспективе разработки приложений. Из всего вышесказанного становится ясной актуальность кроссплатформенных приложений. Получение опыта разработки таких приложений и наглядное демонстрация всей «мощи» кроссплатформенного инструментария и составляет тему данной работы.

    Объект исследования: одно из направлений программирования – кроссплатформенная разработка приложений.

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

    Цель: получение навыков и практического опыта разработки платформо-независимого, графического приложения с использованием фреймворка Qt .

    Задачи:

    1. Изучить актуальность кроссплатформенных приложений.
    2. Разобраться с принципами работы фреймоврка Qt .
    3. Ознакомиться с графическим api OpenGL.
    4. Погрузиться в проектирование пользовательского интерфейса для приложения.
    5. Освоить основные принципы работы с языком запросов SQL,на примере работы с MySQL.
    6. Получить опыт работы с современным средством контроля версий Git, на примере работы с GitHub.
    7. «Поднять» и настроить сервер на FreeBSD.
    8. Разработать программный и пользовательский интерфейс программы.
    9. Создать дистрибутив данной программы и распространить его.

    Используемое ПО

    Фреймворк Qt

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

    Почему стоит использовать Qt?

    Qt предоставляет программисту не только удобный набор библиотек классов, но и определённую модель разработки приложений, определённый каркас их структуры. Следование принципам и правилам «хорошего стиля программирования на C++/ Qt » существенно снижает частоту таких трудно отлавливаемых ошибок в приложениях как утечки памяти (memoryleaks), необработанные исключения, незакрытые файлы или неосвобождённые дескрипторы ресурсных объектов, чем нередко страдают программы, написанные «на голом C++» без использования библиотеки Qt .

    У данного фреймворка имеется ряд преимуществ, из-за которых он и был выбран в качестве главного «наставника» в написании проекта.

    Следует отменить несколько из них:

    1. Кроссплатформенный инструментарий разработки программного (далее – ПО) обеспечения на языке программирования C++.
    2. Несколько видов лицензии распространения ПО, в том числе и бесплатной.
    3. Использование MetaObjectCompiler(MOC) — предварительной системы обработки исходного кода (в общем-то, Qt — это библиотека не для чистого C++, а для его особого наречия, с которого и «переводит» MOC для последующей компиляции любым стандартным C++ компилятором).
    4. Поддержка множества языков программирования, таких как:
      1. C++
      2. PySide
      3. Python– Py Qt
      4. Ruby – Qt Ruby
      5. Java – Qt Jambi
      6. PHP –PHP- Qt


    5. Хорошо продуманный, логичный и стройный набор классов, предоставляющий программисту очень высокий уровень абстракции. Благодаря этому программистам, использующим Qt , приходится писать значительно меньше кода, чем это имеет место при использовании, например, библиотеки классов MFC. Сам же код выглядит стройнее и проще, логичнее и понятнее, чем аналогичный по функциональности код MFC или код, написанный с использованием «родного» для X11 тулкита Xt. Его легче поддерживать и развивать.

    Знакомство с OpenGL

    Так как мы будем разрабатывать платформо-независимую программу, наш выбор пал именно на OpenGL.

    Данная графическая библиотека включает в себя более 250 функций для рисования сложных трёхмерных сцен из простых примитивов.

    В основном используется при создании компьютерных игр, САПР (Система автоматизированного проектирования), виртуальной реальности, визуализации в научных исследованиях.

    Стандарт OpenGL, с появлением новых технологий, позволяет отдельным производителям добавлять в библиотеку функциональность через механизм расширений. Расширения распространяются с помощью двух составляющих: заголовочный файл, в котором находятся прототипы новых функций и констант, а также драйвер устройства, поставляемого разработчиком. Каждый производитель имеет аббревиатуру, которая используется при именовании его новых функций и констант. Например, компания NVIDIA имеет аббревиатуру NV, которая используется при именовании её новых функций, как, например,glCombinerParameterfvNV(), а также констант, GL_NORMAL_MAP_NV. Может случиться так, что определённое расширение могут реализовать несколько производителей. В этом случае используется аббревиатура EXT. В случае же, когда расширение одобряется консорциумом ARB, оно приобретает аббревиатуру ARB и становится стандартным расширением. Обычно расширения, одобренные консорциумом, включаются в одну из следующих спецификаций OpenGL.

    «Змейка»: создание и особенности реализации

    В рамках проекта была разработана программа «Змейка» для демонстрации преимуществ кроссплатформенного фреймворка Qt и графической библиотеки OpenGL; я не ставил перед собой задачу написать программу, которая «взорвёт» рынок, главным было получить практический опыт разработки кроссплатформенных приложений и усовершенствовать свои навыки реального программирования.

    Пользовательский интерфейс программы предполагал таблицу рейтингов, настройки приложения и саму игру.

    Программный интерфейс включал в себя элегантный и переносимый код возможность поддержки, которого реализована с помощью GitHub’a.

    В конечном итоге получился достаточно неплохой готовый продукт. Далее рассмотрим его более подробно.

    Пользовательский интерфейс

    При проектировании пользовательского интерфейса мы выделили несколько пунктов, которые должна содержать наша программа:

    • Настройки
    • Таблица рейтингов
    • Авторизация
    • Игра

    Опираясь на данные пункты, мы сделали первичный интерфейс с помощью Qt Designer.

    Программный интерфейс

    В процессе разработки приложения удалось выделить несколько компонентов программы:

    • Главное окно
    • Окно настроек
    • Окно регистрации/авторизации
    • Виджет игры
    • Логирование
    • Настройки (управление файлом, структурой)
    • База данных
    • Логика игры

    Взаимосвязи элементов изображены в виде схемы, которой мы и руководствовались в процессе разработке.

    Git или система контроля версий

    Так как количество строк кода нашего проекта зашкаливает за 1.000, было принято решение систематизировать поддержку кода, для этого мы используем GitHub.

    GitHub — самый крупный веб-сервис для хостинга IT-проектов и их совместной разработки.

    Сервис абсолютно бесплатен для проектов с открытым исходным кодом (каким мы и являемся) и предоставляет им все возможности, а для частных проектов предлагаются различные платные тарифные планы.

    Данный сервис очень упростил поддержку объёмного кода, в некоторых ситуация даже спасал, когда неожиданно накрылся один из винчестеров на котором разрабатывался проект.

    Для более наглядной демонстрации возможностей github, прилагаю несколько иллюстраций.

    Подготовка и настройка сервера на FreeBSD

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

    Для начала мы выкупили виртуальный сервер у хостера firstvds, процесс оказался довольно не сложный, в связи с тем, что я имел опыт работы с данным хостером и «возведением» серверов/баз данных.

    Для начала к «новоиспечённому» серверу нужно было как-то подключаться, для данной цели мы выбрали, PuTTY — свободно распространяемый клиент для различных протоколов удалённого доступа, включая SSH, который нам и был нужен.

    Далее нам нужно установить MySQL сервер, для этого мы использовали документацию из доверенных источников (ссылка прилагается в списке литературы), предварительно обновив порты (список пакетов).

    После возведения MySQL сервера, нужно было настроить права доступа.

    Как и любой толковый сисадмин, я решил ограничить подключения для всех пользователей кроме того, что был создан для подключения программно по ip.

    Над именем пользователя для программы мы особо не задумывались, по этому, было решено назвать его «programm».

    Из соображений безопасности данный пользователь имел доступ только к базе данных рекордов, о который мы ниже поговорим.

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

    Для администрирования базы данных был выбран MySQL клиент – Navicat.

    Так, как мы будем фиксировать рекорды пользователей, нам нужно их где-то хранить информацию о пользователях и их рекордах.

    Для данной цели было решено создать 2 таблицы:

    • Account – Таблица содержащая информацию о пользователях
    • Record – Таблица содержащая информацию о достижениях пользователей

    В таблице аккаунтов было решено хранить:

    • Id – Уникальный номер записи в таблице
    • Name – Уникальное имя аккаунта
    • Password – Пароль аккаунта (пароль из соображений безопасности хранятся в md5)

    Прилагаю иллюстрацию структур таблиц:

    Из данных иллюстраций ясно видна связь таблицы рекордов и таблицы аккаунтов.

    Под «капотом» (интересные моменты кода программы)

    1. Главное окно

    Разберём самые интересные моменты кода основного окна.

    Как было сказано раньше – Qt очень упрощает жизнь программисту, сейчас мы поймём почему.

    Для того чтобы связать элементы между собой, в нашем случае кнопки, в Qt используется механизм сигналов и слотов.

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

    В данном случае, мы используем «говорящие» названия объектов кнопок, это упрощает восприятие кода.

    Разберём пример с кнопкой выхода.

    В функции connect, мы передаём первый аргумент – объект, от которого ждём сигнал, далее объект, у которого вызывается слот.

    Передаём объект – кнопку выхода, сигнал – нажатие на неё, объект у которого вызывается слот – текущее окно и наконец, сам слот – это закрытие приложения.

    Как было сказано ранее, мы можем добавлять свои слоты.

    Во втором случае так и сделано, мы ожиданием клик, от кнопки настроек, и вызываем слот (функцию) из текущего класса.

    При этом мы должны объявить данный слот:

    После объявления следует описать его.

    Мы разобрались с сигналами и слотами.

    Рассмотрим структуру класса главного окна:

    В арсенале класса имеются:

    • Конструктор, принимающий в виде аргумента родительский виджет.
    • Деструктор.
    • Функция изменения размера окна, которая вызывается при любом изменении главного окна
    • Функция-слот opensettings, функция создания/вызова окна настроек.
    • Функция-слот openrecords, функция создания/вызова окна рекордов.
    • Функция-слот openregistration, функция создания/вызова окна регистрации/авторизации.
    • Функция-слот installsizepolice, функцияфиксации размеров окна на момент начала игры.

    Разберём каждый элемент:

    В данной функции, мы инициализируем систему взаимодействия с базой данных и устанавливаем подключения с сервером.

    Далее, как мы и планировали, передаём информацию об объекте управления базой данных в виджет игры, для взаимодействия с очками.

    Последующие действия устанавливают действия для кнопок, несколько из них мы уже разобрали.

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

    1. Функция изменения размера окна

    Первая и успешно решённая проблема, с которой мы столкнулись: мы используем для движения змейки шаг в 10 пикселей, нам нужно ровное кол-во клеток в сетке:

    Для решения данной проблемы мы меняем разрешение на то, в котором будет целое кол-во клеток. Для начала мы проверяем, поместится ли ровное количество клеток на вертикали. Точно такую же операцию проделываем и для горизонтали.

    Числа 103 и 22, это сдвиг от области главного окна к виджету игры.

    1. Функция создания/вызова окна настроек

    Для начала мы инициализируем само окно (объект окна), заодно передадим ему настройки приложения.

    Далее функция exec поставит фокус на данное окно и отобразит его.

    После закрытие окна, управление опять передаётся в основное окно, и мы успешно устанавливаем фокус на виджет с игрой.

    1. Функция создания/вызова окна рекордов

    Всё аналогично предыдущему случаю, мы создаём объект окна и передаём в качестве аргумента указатель на наш объект управления базой данных.

    1. Функция создания/вызова окна регистрации/авторизации

    Инициализации объекта окна, передача настроек приложения и базы данных.

    2. Настройки. Один из методов работы с конфигурационными файлами

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

    Для начала обратимся к структуре нашего класса:

    Перейдём непосредственно к описанию каждой функции

    Для начала мы инициализируем объект класса QSettingsfsettings, передав ему имя файла с настройками и его формат.

    QVariant QSettings::value ( const QString & key, const QVariant & defaultValue = QVariant() ) const

    Возвращает значение для настройки key. Если настройка не существует, то возвращает значение по умолчанию defaultValue.

    Если файл настроек содержит значения параметров, то они будут записаны в переменные, в противном случае, будут записанные те, которые мы указали как defaultValue.

    1. Установка режима отображения количества кадров в секунду

    void Settings::setValue ( const QString & key, const QVariant & value )

    Устанавливает значение настройки key в значение value. Если key уже существует, то предыдущее значение перезаписывается.

    void QSettings::sync ()

    Записывает любые несохранённые данные в постоянное хранилище и перезагружает любые настройки, которые были к тому времени изменены другим приложением.

    1. Установка режима проигрывания звуков

    Выполняются аналогичные действия пункту 2.

    1. Установка режима отображения матрицы

    Матрицу, про которую идёт речь, мы уже видели в предыдущем разделе в пункте «Функция изменения размера окна».

    1. Установка имени аккаунта

    В данной функции происходит сохранение имени пользователя.

    Следует заметить, что пароль сохраняется в зашифрованном виде (md5).

    1. Установка статуса авторизации

    Данный параметр помогает нам понять, прошёл ли пользователь авторизацию.

    1. Получения статуса отображения количества кадров в секунду

    Функция возвращает статус отображения fpsво время работы приложения.

    1. Получения статуса проигрывания звуков

    На основе возвращённого ответа функции, мы можем сделать вывод, проигрывать ли звук.

    1. Получения статуса режима отображения матрицы

    На основе возвращённого ответа функции, мы можем сделать вывод, нужно ли отображать матрицу/сетку во время работы приложения.

    1. Получения имени пользователя

    Функция возвращает имя пользователя, которые мы можем использовать в дальнейших целях.

    Функция возвращает зашифрованный пароль пользователя.

    1. Получения статуса авторизации пользователя

    На основе возвращённого ответа функции, мы можем сделать вывод, имеет ли смысл дальнейших действий с аккаунтом пользователя.

    Именно так выглядит работа простого механизма изнутри.

    Иллюстрация конфигурационного файла:

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

    3. Окно настроек

    Настройки – являются не отъемлемой частью приложения, но для того чтобы с ними взаимодействовать, нужен специальный интерфейс, в нашем случае таким интерфейсом будет являться окно.

    Со стороны пользователя все, кажется «лёгко», именно так оно и будет, если мы используем Qt .

    Рассмотрим класс окна:

    Именно правильный программный интерфейс и каноническая реализация даёт простой и понятный код.

    Для начала нам нужно проинициализировать объект класса настроек. Далее мы установим на чекбоксы значения аргументов из настроек. После нажатие на кнопку «ОК» мы сохраняем настройки.

    Всё просто. Мы сохраняем значения из чекбоксов в настройки.

    Именно на данном примере явно видны преимущества использования Qt .

    4. База Данных

    Система управления базами данных (СУБД) — совокупность программных и лингвистических средств общего или специального назначения, обеспечивающих управление созданием и использованием баз данных.

    Qt дает возможность создания платформо-независимых приложений для работы с базами данных, используя стандартные СУБД. Qt включает «родные» драйвера для Oracle, Microsoft SQL Server, Sybase Adaptive Server, IBM DB2, PostgreSQL, MySQL и ODBC-совместимых баз данных. Qt включает специфичные для баз данных виджеты, а также поддерживает расширение для работы с базами данных любых встроенных или отдельно написанных виджетов.

    Работа с базами данных в Qt происходит на различных уровнях:

    1.Слой драйверов — Включает классы QSqlDriver, QSqlDriverCreator, QSqlDriverCreatorBase, QSqlDriverPlugin и QSqlResult. Этот слой предоставляет низкоуровневый мост между определенными базами данных и слоем SQL API.

    2.Слой SQL API — Этот слой предоставляет доступ к базам данных. Соединения устанавливаются с помощью класса QSqlDatabase. Взаимодействие с базой данных осуществляется с помощью класса QSqlQuery. В дополнение к классам QSqlDatabase и QSqlQuery слой SQL API опирается на классы QSqlError, QSqlField, QSqlIndex и QsqlRecord.

    3.Слой пользовательского интерфейса — Этот слой связывает данные из базы данных с дата-ориентированнымивиджетами. Сюда входят такие классы, как QSqlQueryModel, QSqlTableModelи QSqlRelationalTableModel.

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

    Для начала нам нужно создать структуру базы данных, которую мы будем возвращать.

    Рассмотрим структуру СУБД:

    Обратите внимание на переменные, в которых мы указываем данные для подключения к серверу.

    Пояснение: Во время написание конкурсной работы было решено, не скрывать части данных для соблюдения безопасности работы сервера.

    Заглянем под «капот» субд.

    На данном этапе мы указываем, какой из драйверов использовать, в нашем случае QMYSQL.


    Далее указываем данные для подключения к базе данных.

    1. Функция подключения к базе данных

    Изначально мы вызываем функцию open, которая возвращает статус, успешно ли произведено подключение.

    В случае неуспешного подключения, будет выведена причина неудачного подключения.

    1. Функция отключения от базы данных

    В функции удаляется глобальное подключение объекта к базе данных. Далее закрывается подключение к базе данных.

    1. Функция создания аккаунта для пользователя (API)

    Для начала нам нужно проверить, имеется ли уже такой аккаунт, если имеется, то прекратить регистрацию.

    QsqlQuery — набор средств управления выражениями SQL и их выполнения.

    Укажем базу данных, которую мы будем использовать, в нашем случае db.

    Далее нам нужно создать запрос.

    Данный запрос выполнит вставку в таблицу account запись с указанным именем и зашифрованным паролем.

    Скорее всего, вы заметили, что в запросе мы не указали имя и пароль, а поставили:name и password. Данные выражения будут заменены на переменные, которые мы указываем ниже. Имя остаётся без изменения. Пароль преобразуется из нормального вида в md5.

    Далее мы выполняем данный запрос, если запрос выполнен успешно, мы добавляем игрока в таблицу рекордов, в противном случае выдаём ошибку.

    1. Авторизация пользователя (API)

    Данная функция возвращает true – в случае успешной авторизации, false–в противном случае.

    Данная функция предоставляется в двух экземплярах, 1 для работы с зашифрованным паролем и 2 для работы с не зашифрованным паролем.

    В функции мы создаём запрос и ищем пользователя, так, как мы указали явно вывести нам либо одну запись, либо ничего. Мы получим либо 1 запись, либо 0. Только в случае полного совпадения логина и пароля мы получим запись. Поэтому количество записей можно использовать, как возвращающееся значение.

    1. Установка кол-во набранных очков (API)

    Данная функция, по имени пользователя, обновляет его количество набранных очков.

    Также мы используем значение bool (newacc), при создание нового аккаунта, мы не обновляем, а добавляем запись в таблицу.

    1. Проверка на занятость аккаунта (API)

    В данной функции, мы определяем, существует ли пользователь с данным именем.

    1. Получение уникального идентификатора пользователя по имени аккаунта (API)

    Функция в случае успешного выполнения, возвращает уникальный идентификатор пользователя по его имени аккаунта.

    1. Получение имени аккаунта по уникальному идентификатору

    В данной функции мы получаем имя аккаунта, по уникальному идентификатору.

    1. Получения записи из таблицы рекордов по уникальному идентификатору

    Данная функция возвращает структуру, в которой содержится имя аккаунта и его рекорд. Все действия выполняются с помощью уникального идентификатора пользователя.

    1. Получения списка рекордов всех участников игры «Змейка» в порядке убывания (API)

    Данная функция возвращает вектор структур записей о рекордах.

    В запросе присутствует ключевое слово DESC, которое устанавливает порядок вывода (убывание/возрастание).

    В данном разделе мы полностью рассмотрели СУБД программы. Ознакомились с основами языкаSQL, поняли принцип работы с бд в Qt . В следующих разделах мы будем активно использовать рассмотренную СУБД.

    5. Таблица рекордов

    Неотъемлемая часть спортивного интереса – это таблица рекордов. Практически ни одна игра не обходится без данной функции.

    На настоящий момент программа была уже опробована несколькими людьми.

    Для начала мы устанавливаем текущую базу данных. Далее мы выполняем запрос получения списка рекордов всех игроков.

    В цикле мы создаём новую запись в таблице и заполняем её данными из вектора.

    6. Виджет игры «Змейка»

    Данный виджет выполняет основную роль – рисования.

    Виджет содержит в себе настройки приложения, змейку, базу и пару таймеров (для чего, скоро поймём).

    Для обновления виджета, мы будем использовать таймер, который после заданного интервала, будет вызывать функцию обновления.

    Наш виджет унаследован от QGLWidget.

    Укажем несколько особенностей используемого виджета:

    QGLWidget так устроен, что при первой инициализации класса он автоматически вызывает методы в следующем порядке:

    При запуске: initializeGL()->resizeGL()->paintGL()

    При изменении размера окна: resizeGL()->paintGL()

    updateGL() вызывает paintGL()

    initializeGL — необходимо использовать для глобальных настрое построения изображения, которые нет необходимости указывать при построении кадра.

    resizeGL — служит для построения размера окна. Если в ходе работы изменится размер окна, но не изменить область просмотра, то при увеличении размера можно наблюдать непредсказуемые явления.

    paintGL — этот метод будет выстраивать каждый наш кадр для отображения.

    Для хранения размеров виджета нам понадобятся пару переменных, также нам нужны будут переменные для хранения текущего количества кадров(fps) и количества набранных очков, также нужно хранить шаг для сетки и системные состояния, к примеру, о начале игре или о нажатии клавиш.

    Рассмотрим класс виджета:

    Сейчас более подробно рассмотрим каждый из методов класса.

    В первую очередь мы принимаем СУБД, далее создаём объект настроек приложения, устанавливаем интервал для случайных значений и двойную буферизацию (двойная буферизация позволяет более корректно заменять изображение, чтобы не происходили скачки на экране: PaintGL сразу картинку не рисует на экран, а заносит в буфер, а по запросу swapBuffers() заменяет текущее изображение на то, что появилось в буфере).

    На следующем этапе мы устанавливаем таймера, первый таймер, для обновления виджета, а второй — для змейки.

    В данной функции мы

    Обнуляем кол-во набранных очков,

    Создаём новый экземпляр змейки.

    Устанавливаем границы поля.

    Устанавливаем состояние игры.

    И убираем логотип игры.

    Устанавливаем фокус на нашу змейку

    И запускаем таймер.

    Так как змейка погибает, мы проигрываем звук поражения.

    Устанавливаем состояние игры на false, при этом состояние о поражении переводим в true.

    Только после данных действий, мы останавливаем таймер змейки и удаляем её экземпляр.

    Дальше мы проверяем, авторизирован ли игрок, если да, то проверяем рекорд, если он превзошёл свой рекорд, то обновляем его и показываем поздравление.

    1. Изменение размера виджета (Event)

    Данная функция вызывается при изменении размера окна, из-за которого меняется размер виджета.

    На время изменения размера, мы устанавливаем режим матрицы проекции.

    Далее загружаем матрицу.

    Изменяем область вывода изображения.

    Запоминаем новые размеры виджета.

    Посылаем змейке запрос на изменение размера поля.

    1. Функция обработки нажатий клавиш (Event)

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

    Также по нажатию клавиши Escape, игры завершается.

    1. Функция, возвращающая настройки программы

    Функция возвращает указатель на настройки приложения.

    1. Функция инициализации настроек OpenGL

    В данном методе мы устанавливаем чёрный цвет очистки экрана.

    Функция возвращает состояние игры.

    1. Функция подсчёта кол-во кадров в секунду (FPS)

    В данной функции мы высчитываем кол-во кадров. Мы смотрим если время в секундах сейчас больше, чем было в прошлый раз, что сохраняем значение кадров.

    Если оно не изменялось, то увеличиваем кол-во кадров (секунда не прошла)

    1. Функция рисования интерфейса

    Первым делом, выбираем цвет рисования, т.к. линия у нас должна быть белой, мы устанавливаем белый цвет.

    Далее нам нужно нарисовать линию от одного края к другому, для этого мы вычисляем нужные значения и рисуем их.

    Также нужно вывести кол-во набранных очков, для этого воспользуемся методом Qt , и выведем его.

    Получим из настроек состояние отображения fps, если нужно выведем кол-во fps.

    1. Функция рисования сетки

    В данном методе, мы устанавливаем серый цвет вывода и выводим линии, начиная от одного края к другому как по горизонтали, так и по вертикали.

    При этом по горизонтали от низа мы делаем отступ интерфейса.

    1. Основная функция рисования paintGL (Event)

    Для начала мы установим буфер глубины и буфер цвета.

    Далее установим матрицу проекции и включим её.

    Определим координатную систему с помощью glOrtho, в нашем случае начало координат будет в правом верхнем углу.

    Проверяем, если состояние игры положительное, то рисуем змею и еду, в противном случае проверяем, нужно ли показывать логотип, если нет, то смотрим, погибла ли наша змейка, если да, то выведем, сколько очков мы набрали. Далее смотрим по настройкам, если есть указание рисовать матрицу, рисуем её, также поступаем и с подсчётом fps. В любом случае рисуем интерфейс.

    1. Функция действий змейки

    В данной функции, происходит взаимодействие с самой змейкой, основное действие — это её движение.

    Далее мы проверяем, не столкнулась ли змейка, ни с кем из своих звеньев.

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

    На этом можно закончить разбор рисования, дальше мы обсудим логику самой змейки.

    7. Логика «Змейки»

    В этой главе было решено объединить 2 класса, это класс, самой змейки и класс её звеньев.

    Приступим к заключительной части категории «Под капотом».

    Рассмотрим 2 класса:

    В функции рисования, мы пробегаемся по массиву звеньев и рисуем каждое из них

    В данном методе, мы смотрим, является ли данная еда «мега», если да, то устанавливаем зелёный цвет, для рисования.

    Далее мы рисуем квадрат в пределах заданных координат.

    1. Установка размеров поля

    В данной функции, мы устанавливаем данное значение для каждого звена и запоминаем его для себя.

    Данная функция используется для прикрепления нового звена к змейке. Она использует алгоритм расчёта последней клетки, последнего звена и на её место ставит текущее (новое) звено. Также для него оно устанавливает идентичное направление.

    1. Изменение направления движения змейки

    Для начала нам нужно узнать, можно ли изменить направление и готово ли звено его принять. Только после этого мы можем установить значение.

    Далее используем очень хитрый алгоритм. Когда звено доходит до определённых координат оно меняет направление. Данная процедура повторяется для каждого звена.

    Первым делом мы инициализируем музыку. Далее мы создаём «голову» звено и ставим ему направление движения.

    1. Автоматическое движение змейки

    В данной процедуре мы получаем направление движение каждого звена и двигаем его в том же направление, из-а чего создаётся эффект движения змейки.

    Данные функции участвуют в проверке столкновения, первая проверяет, не совпадают ли координаты головы и любого из звена, если совпадает, то сообщаем о столкновении.

    Метод генерирует в случайной точке еду, по достижении пяти «простых» поеданий еды, генератор генерирует специальную «мега» еду, которая даёт больше очков.

    Также мы используем алгоритм, который не даёт вылезти еде за края поля.

    Имеет место и проверка, не оказалась ли еда в звене или в том же самом месте.

    1. Проверка на столкновение с едой

    Метод проверяет, не столкнулась ли голова с едой.

    В данных методов вызывается метод play, который проигрывает музыку.

    В конструкторе происходит присваивание локальным переменным значения аргументов. Координаты и направление движения.

    Похожий пример, мы уже разбирали, когда говорили о рисовании еды. В данном случае всё идентично.

    Данные функции отвечают за передвижение звена, в них происходит изменение значения координат и проверка на выход за пределы поля.

    1. Изменение направления движения с учётом координат

    Выполняется проверка, нужно ли изменить направление движения на текущих координатах.

    1. Проверка выхода за поля

    Дистрибутив игры

    В качестве ПО для создания дистрибутива был выбран SmartInstallMarker.

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

    Заключение

    Задачи, поставленные в начале работы над проектом, выполнены, цель доcтигнута. Исходный код представлен в git репозитории.

    Литература

    1. Standard C++ Library reference URL: http://cplusplus.com/reference/ Время доступа: 19.01.14
    2. Qt Documentation URL: http://doc.qt.digia.com/ Время доступа: 20.01.14
    3. OpenGL 4 Reference URL: http://opengl.org/sdk/docs/man/ Время доступа: 20.01.14
    4. Koenig A. Accelerated C++.-2002
    5. Lafore R/ Object-Oriented Programming in C++.-2011

    Рекомендуем прочитать:

    4 Комментарии “ Технология разработки визуальных кроссплатформенных приложений с использованием фреймворка Qt на примере программы “Snake” ”

    На раскрыта тема «кроссплатформенных приложений» указанная в заголовке. Все остальное (почти) туфта. Зачем упоминание про термины типа СУБД? Или это академическая статья включая тексты из википедии? ��
    При чем тут FreeBSD вообще? Частный субъективный случай реализации задачи взаимосвязи игроков и только.

    СУБД использовалось для примера работы с базой данных, статья писалась как научная работа в 10 классе

    Цукерберг рекомендует:  Freelancer - Начинающий веб-программист
    Понравилась статья? Поделиться с друзьями:
    Все языки программирования для начинающих