Создание графического интерфейса на си. Методология разработки приложений с использованием форм. Работа со справочной системой

C++ - один из самых мощных и востребованных языков программирования. Ежедневно на нём пишут сотни приложений, зачастую использующих GUI. Однако работа с графикой не всегда удобна программисту - в таком случае применяют готовые графические библиотеки. Они позволят сделать разработку графической части приложений максимально быстрой и удобной.

SFML

Qt

Кроссплатформенная библиотека Cocos2D-X призванна упростить разработку мобильных игр. Поддерживает все те же платформы, что и Qt. Из плюсов стоит отметить доступность, удобство эксплуатации и создание отдельного конструктора игр, основанного на библиотеке Cocos Creator . В списке игр, основанных на движке, есть всемирно известная BADLAND, работающая на всех доступных платформах.

Кое-что ещё

Если при создании игры вам нужно работать с графикой и анимацией в больших объёмах, то лучше использовать Unity вместо Cocos2D-X. В Unity имеется возможность плавной интеграции с такими инструментами, как Photoshop, Maya или Blender. В Cocos2D-X вся графика добавляется извне и на неё ссылаются из кода.

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

Juce

Пожалуй, одна из самых известных графических библиотек. GTK+ - графический фреймворк, широко применямый во многих системах. Изначально он задумывался как компонент GIMP, но за 20 лет после выпуска первой стабильной версии он нашёл применение в сотнях других приложений.

Сейчас GTK+ - полноценный графический фреймворк, не уступающий тому же QT. Он поддерживает разные языки программирования и продолжает развиваться.

Кое-что ещё

В своё время библиотека создавалась в качестве альтернативы Qt, которая была платной. GTK+ - один из немногих фреймворков, которые поддерживают язык C. Библиотека кроссплатформенная, но есть мнение , что программы на Linux выглядят более нативно, чем на Windows или Mac (GTK+ хорошо поддерживается даже на KDE). Интересно, что из-за некоторых проблем с кроссплатформенностью Wireshark перешла на Qt.

Пример первой программы можно посмотреть на Википедии .

Другие интересные статьи по C++ можно посмотреть у нас .

Заключение

Выше представлены наиболее популярные технологии для работы с GUI не только на C++, но иногда и на других языках (например, Qt и GTK+). Однако всегда следует учитывать особенности той или иной технологии. Выпишите список функций своего приложения, ещё раз прочитайте описания всех библиотек и фреймворков, и только после этого выбирайте то, что действительно подходит больше всего для проекта.

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

13.1 Виджеты (Widgets)

Виджеты (Widgets ) - это визуальные элементы, из которых состоит графический интерфейс пользователя.

Примеры виджетов:

  • Кнопка (класс QPushButton );
  • Метка (класс QLabel );
  • Поле ввода (класс QLineEdit );
  • Числовое поле-счётчик (класс QSpinBox );
  • Строка прокрутки (класс QScrollBar ).

В Qt есть около 50-ти готовых классов графических элементов доступных для использования. Родительским классом для всех виджетов является класс QWidget . От него наследуются все главные свойства визуальных элементов, которые мы тщательно рассмотрим. Исследование способов разработки программ с графическим интерфейсом начнём с примера.

Создадим пустой файл проекта. Запустим мастера проектов и выберем в разделе Projects (Проекты) пункт Other Project (Другой проект) . Далее выберем тип проекта Empty Qt Project (Пустой проект Qt) . К файлу проекта добавим содержимое:

TEMPLATE = app #Модули Qt, которые мы будем использовать QT += widgets #Добавляем модуль widgets для работы с виджетами (необходимо для Qt5). TARGET = widget#Название исполняемого файла SOURCES += \ main.cpp

Теперь создадим простую программу с окном, в котором мы будем выводить надпись. Установим размер окна и текст его заголовка, а также установим шрифт для надписи. Для этого создадим файл main.cpp со следующим содержанием:

#include #include int main (int lArgc, char * lArgv ) { //Создаём объект QApplication, который инициализирует и настраивает оконную программу, //управляет её выполнением с помощью цикла обработки событий QApplication lApplication (lArgc, lArgv); QLabel lLabel; //Создаём виджет QLabel - метка lLabel.setText (" I am widget! "); //Задаём текст для метки lLabel.setGeometry (200, 200, 300, 150); //Задаём размеры - позицию (x, y) ширину и высоту. Задаём выравнивание текста lLabel.setAlignment (Qt::AlignHCenter | Qt::AlignVCenter); //Класс QFont используют для настройки параметров шрифта. //Выбираем семейство шрифтов Arial Black и размер 12. QFont lBlackFont (" Arial Black ", 12); lLabel.setFont (lBlackFont); //Задаём шрифт для метки lLabel.show (); //Вызываем метод show() для показа метки на экране. return lApplication.exec (); //Запускаем программу на выполнение exec() выполняет //цикл обработки событий. Программа ожидает действия пользователя и выполняет их обработку. }

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


Рис. 13.1.

Для создания структуры виджеты организовывают в иерархию по принципу "часть - целое". Каждый из виджетов может содержать другие виджеты. Такой визуальный элемент становится "родителем" (родительским виджетом) для элементов, которые он содержит. Отметим, что такие отношения не следует путать с наследованием в C++ - отношениями между классами в программе. Отношения между виджетами являются отношениями между объектами. Такие отношения порождают несколько последствий:

  • родительский элемент будет отвечать за удаление дочернего элемента: если родительский виджет удалят - то он автоматически удалит и все дочерние элементы;
  • родительский виджет размещает дочерние виджеты внутри себя, части дочерних виджетов, которые выходят за пределы родителя будут невидимыми;
  • часть состояния родительского виджета передаётся дочерним - это касается некоторых свойств (видимость, активность) и стилей, которые накладываются на визуальный элемент.

Виджеты, которые не имеют родителя (виджеты верхнего уровня), имеют вид отдельных окон в программе. Рассмотрим пример. Назовём новый проект ParentExample . Файл проекта будет содержать обычные для GUI -проекта настройки:

TEMPLATE = app TARGET = ParentExample QT += widgets

Для виджета, который мы будем использовать в качестве главного окна создадим новый класс. Для этого в категории Files and Classes (Файлы и классы) выберем раздел С++ и выберем С++ Class (см. рис. 13.2).

Следующим шагом будет создание нескольких элементов на окне. Для этого откроем файл parentwidget.cpp и изменим код конструктора класса. Для отображения элементов достаточно создать их в конструкторе класса и задать ParentWidget как отца для них. Код parentwidget.cpp выглядит так:

#include " parentwidget.h " #include #include #include ParentWidget::ParentWidget (QWidget * parent) : QWidget (parent) { //Создаём метку, указывая родительский виджет - this, то есть экземпляр класса ParentWidget. QLabel * lLabel=new QLabel (this); //Позиция относительно левого верхнего угла родительского виджета. lLabel ->setGeometry (50, 0, 100, 30); lLabel ->setText (" TextLabel "); //Текст на метке. //Создаём кнопку, задаём "родителя", геометрию и текст QPushButton * lPushButton = new QPushButton (this); lPushButton->setGeometry (50, 50, 100, 30); lPushButton->setText (" PushButton "); //Создаём поле ввода, задаём "родителя", геометрию и текст QLineEdit * lLineEdit = new QLineEdit (this); lLineEdit ->setGeometry (50, 100, 100, 30); lLineEdit ->setText (" LineEdit "); lLineEdit ->selectAll (); //Выделяем текст в поле ввода (просто для примера) //Наконец изменяем размер родительского виджета setGeometry (x (), y (), 300, 150); //и задаём текст заголовка окна setWindowTitle (" parent widgetExample "); }

Поскольку родительским элементом является ParentWidget , то метка (QLabel ), кнопка (QPushButton ) и текстовое поле (QLineEdit) находятся в его пределах. Позицию дочерних виджетов задают относительно левого верхнего угла отца. В этом легко убедиться изменив размеры и позицию окна нашей программы. Обратите внимание на то, как мы создавали элементы пользовательского интерфейса в динамической памяти используя оператор new . Это гарантирует, что элементы не будут удалены после завершения работы конструктора ParentWidget .

5

Я сделал много разных разделов GUI-системы для Nintendo DS, таких как кнопки и текстовые поля и флажки, но мне нужен способ скрыть эти классы в одном классе Gui, чтобы я мог рисовать все на экране все сразу, и сразу проверьте все кнопки, чтобы проверить, нажаты ли какие-либо кнопки. Мой вопрос - как наилучшим образом организовать все классы (например, кнопки и текстовые поля) в один GUI-класс?

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

Edit: Я использую C++.

Class Gui { public: void update_all(); void draw_all() const; int add_button(Button *button); // Returns button id void remove_button(int button_id); private: Button *buttons; int num_buttons; }

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

  • 5 ответов
  • Сортировка:

    Активность

2

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

Я какое-то время что-то искал, я консультировался с некоторыми книгами и VTMs , и до сих пор это приблизительная идея простых систем ui.

Class uiElement() { ... virtual void Update() = 0; virtual void Draw() = 0; ... } class uiButton() public: uiElement { ... virtual void Update(); virtual void Draw(); ... } class uiTextbox() public: uiElement { ... virtual void Update(); virtual void Draw(); ... } ... // Other ui Elements class uiWindow() { ... void Update(); void Draw(); void AddElement(uiElement *Element); void RemoveElement(uiElement *Element); std::list Elements; ... } void uiWindow::Update() { ... for (list ::iterator it = Elements.begin(); it != Elements.end(); it++) it->Update(); ... } void uiWindow::Draw() { ... for (list ::iterator it = Elements.begin(); it != Elements.end(); it++) it->Draw(); ... }

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

У меня пока ничего не работает, так как у меня проблемы с кодом рисования. С различными API-интерфейсами на ПК и PSP я просматриваю код оболочки для OpenGL и psp gu.

Надеюсь, это поможет.

0

Одна полезная стратегия, которую следует иметь в виду, может быть composite pattern . На низком уровне он может позволить вам легче обрабатывать все объекты GUI (и коллекции объектов) после их создания. Но я не знаю, что связано с дизайном графического интерфейса GUI, поэтому одно место, чтобы найти общее вдохновение, - это исходный код существующего проекта. WxWidgets - это кросс-платформенный графический интерфейс с доступным исходным кодом. Удачи с вашим проектом!

0

3

Для тех, кто заинтересован, вот мой с открытым исходным кодом, BSD-лицензированные GUI инструментарий для DS:

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

Если вы не поддержите это в базовом классе, вы столкнетесь с серьезными проблемами при попытке реализовать что-либо более сложное, чем текстовое поле и кнопку. Например:

  • Табличные панели можно смоделировать как несколько кнопок, сгруппированных в единый родительский элемент пользовательского интерфейса, который обеспечивает взаимную исключительность выбора;
  • Группы радиостанций (с течением времени);
  • Полосы прокрутки могут быть представлены как элемент слайдера/желоба и кнопки вверх/вниз;
  • Списки прокрутки могут быть представлены в виде контейнера и нескольких элементов пользовательского интерфейса.

Кроме того, стоит помнить, что у DS есть процессор с частотой 66 МГц и 4 МБ ОЗУ, который используется как для хранения вашей программы, так и для ее выполнения (DS-диски загружаются в ОЗУ до их запуска). Вы действительно должны рассматривать его как встроенную систему, что означает, что STL отсутствует. Я удалил STL из Woopsi и сумел сохранить 0.5MB. Не так много по настольным стандартам, но это 1/8 от общей доступной памяти DS, потребляемой STL-мусором.

Я подробно весь процесс написания пользовательского интерфейса на моем блоге:

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

В этой статье речь пойдет о создании простейших приложений с использованием форм на языке C++. Сразу хочу внести ясность: разработка «формовых» С++ приложений будет осуществляться в среде Microsoft Visual Studio (обойдем стороной главного конкурента от компании Borland Software). Стоит отметить, что в Visual Studio есть два способа сделать приложение с формами, решение принимается в момент создания нового проекта.

Первый из них - использовать Windows Forms, реализующий графический интерфейс пользователя и входящий в Microsoft.NET Framework. Данный подход упрощает доступ к интерфейсным элементам Microsoft Windows благодаря созданию обёртки для Win32 API в управляемом коде. Если изложить свои мысли в более понятной форме, то данный подход очень схож с построением консольного приложения, но чуть более сложен т.к. использует формы.

Второй способ основан на использовании Microsoft Foundation Classes (MFC), библиотеке, которая берет на себя заботу о создании каркаса приложения. В отличие от первого, MFC «из коробки» использует патерн MVC (Model-View-Cont roller). Данный подход сложнее первого, но опираясь на него можно запросто создать каркас для весьма интересных приложений, к примеру, текстового редактора или использовать компонент Ribbon и сделать меню как в небезызвестном MS Office 2010.

Создание приложения в MS Visual Studio

Давайте создадим новое приложение: File->New->Project. В появившемся окне как на рисунке выше найдите и выберите Windows Forms Application, далее укажите название (app1) и расположение нового проекта и подтвердите его создание нажатием кнопки «OK».

Прежде чем приступить непосредственно к программированию, следует понять, что такое событие. Событие это действие, которое происходит при определённых условиях. Самыми простыми (и наиболее распространенным и) можно считать Load,Click… рассмотрим некоторые из них более подробно:

  • Activated - событие, возникающее при активизации элемента.
  • Click - возникает при одиночном нажатии на элемент.
  • DoubleClick - двойной щелчок по элементу.
  • HelpRequested - срабатывает при нажатии клавиши .
  • Paint - возникает, когда элемент перерисовывается.
  • MouseLeave - событие срабатывает, когда курсор покидает границы элемента.

Не стоит забывать, что свойственные элементу события зависят от его типа. Чтобы просмотреть все доступные для объекта формы события следует выделить его и в окне свойств выбрать значок молнии. Ниже показана часть событий для элементаForm1. Как можете видеть для события Load выбрана функция Form1_Load, следовательно код, содержащийся в этой функции будет вызван при загрузке формы.

Откройте файл Form1.h, там будет такой код:

Private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e){ }

Это та самая функция Form1_Load, срабатывающая при загрузке формы. Давайте убедимся в этом, добавив на форму компонент TextBox.

Для этого откройте ресурс формы и выделите его. Далее выберите панель с инструментами Toolbox и перетащите компонент TextBox на форму. Модифицируйте функцию Form1_Load следующим образом:

Private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { textBox1->Text = "Hello, World!"; //textBox1 – имя добавленного вами текст бокса }

Запустите проект, в итоге должно появиться следующее сообщение:

На этом пока все, продолжение в следующих уроках.



Понравилась статья? Поделиться с друзьями: