Приветствую хабросообщество!
Наверно каждый кто профессионально разрабатывает ПО или просто увлекается программированием, рано или поздно приходил к необходимости создавать пользовательский интерфейс для своей программы. И если не рассматривать нативные для платформ окружения и языки такие как C# для Windows или Objective-C для Mac OS X которые изначально содержат средства для визуализации интерфейса, то выбор оказывается не очень богатым, особенно если мы не горим желанием платить деньги за средства разработки GUI или желаем добиться кроссплатформенности.
В своем первом посте на Хабре я бы хотел рассказать о таком фремворке как JUCE. Поиск по Хабру выдал всего 2 статьи где данный фреймворк только упоминается, но ни какой детальной информации не приводится. Думаю что тем кто только начинает осваивать кроссплатформенные GUI приложения на C++ будет интересно узнать об альтернативе таким монстрам как Qt или таким старичкам как GTK+
Что такое JUCE
Официальный сайт разработчиков: juce.com.
JUCE (Jules’ Utility Class Extensions) это всеохватывающая библиотека классов С++ для разработки кроссплатформенного программного обеспечения.
Он содержит практически все что вам может понадобиться для создания большинства приложений, особенно хорошо подходит для построения сложных GUI, обработки графики и аудио.
Juce — это открытый кроссплатформенный инструментарий разработки ПО (фреймворк) для языка C++, используемый для разработки GUI приложений и плагинов.
JUCE поддерживает следующие платформы и возможности:
- Mac OS X Приложения и VST/AudioUnit/RTAS/NPAPI плагины компилируются при помощи Xcode. (на 10.7.5 & Xcode 4.6.3 все работает без проблем)
- Windows Приложения и VST/AudioUnit/RTAS/NPAPI/ActiveX плагины собираются при помощи MS Visual Studio. Результаты полностью совместимы с Windows XP, Vista и Win7/8
- Linux Приложения и плагины могут быть собраны для любого ядра версии 2.6 и старше.
- iOS Нативные iPhone и iPad приложения собираются при помощи Xcode
- Android Android приложения собираются при помощи Ant или Eclipse с использованием Android NDK.
JUCE разрабатывался силами одного человека и из набора классов для личного использования перерос в полноценный фреймворк.
OpenSource лицензия появилась в 2003 году, а с 2005 фреймворк обзавелся платной ее версией для закрытого ПО.
Большинство модулей фреймворка имеют открытую лицензию GPLv2, v3 и AGPLv3, модуль Core имеет лицензию ISC
Если у вас нет желания публиковать исходный код своей программы, то вы можете приобрести коммерческую лицензию по следующим расценкам:
- Лицензия на один продукт — 399 Английских Фунтов
- Лицензия на неограниченное колличество продуктов — 699 Фунтов
- Апгрейд с первой на вторую — 349 Фунтов
- Апгрейд старых версий — до полной 349 Фунтов до лицензии на один продукт 199 Фунтов
Состав фреймворка и начало работы
Сам JUCE достаточно легковесный, чуть более 28 Мб. Папка docs содержит подробную документацию по установке и подключению фреймворка в различных ОС и средах разработки.
Касательно установки стоит заметить что JUCEпредставляет собой не набор библиотек в привычном смысле или набор исходников из которых вы должны собрать библиотеки для статической или динамической линковки, а набор заголовочных файлов и файлов исходного кода, содержащие все предоставляемые фреймворком классы. Данный подход не только упрощает миграцию с одной платформы на другую, избавляя вас от необходимости включать в состав дистрибутивов библиотеки фреймворка или требовать их наличия на компьютере пользователя, но и решает проблему разрядности библиотек от которых зависит фреймворк. Так как стандартные библиотеки или стандартное окружение современных ОС которое используется в проектах JUCE (все они описываются в документации поставляемой в комплекте с фреймворком) как правило собраны с поддержкой как 32 так и 64 bit. Так что вам стоит следить за битность только тех библиотек которые вы дополнительно используете в своем проекте.
Все модули фреймворка находятся в папке modules. Весь исходный код хорошо структурирован и комментирован, так что проблем с пониманием возникнуть не делжно.
В папке extras можно найти примеры использования фреймворка. Среди прочего там же вы найдете две утилиты, которые помогут вам в разработке. Для этих утилит, да и для всех примеров, уже есть готовые проекты для различных платформ и IDE, все что вам остается это открыть проект и скомпилировать пример или утилиту.
Первая утилита это Introjucer, достаточно аскетичная программа для автоматической генерации проектов, написана с использованием самого JUCE и является ярким примером возможностей фреймворка. В комплекте присутствует мастер по созданию проектов, мастер по созданию шаблонов исходно кода и очень весомое дополнение — визуальный редактор GUI, который просто генерирует на основе ваших манипуляций код на С++ в соответствующий файл исходного кода (который до того был создан при помощи мастера шаблонов), редактор кода, мастер локализации и ряд других достаточно полезных инструментов.

Редактор кода

Редактор GUI

Добавление sourcecode файлов
Приятной изюменкой в Introjucer является наличие собственного файла проекта, настроенного под все IDE и платформы которые поддерживаются фреймворком. Для переноса кода от разработчика не потребуется ни чего, кроме наличи на целевой системе утилиты Introjucer. Каждый проект сформированный утилитой можно открыть в целевой IDE которую вы используете для своей ОС.

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

Hello World
И куда же без примера кода…
Рассмотрим подробнее пример поставляемый с фреймворком:
../extras/example projects:
В проектах JUCE все заголовочные файлы в конечном итоге вкладываются в один файл "../JuceLibraryCode/JuceHeader.h".
Так что разработчику не приходится подключать весь ворох классов из фреймворка вручную в каждом исходном файле.
В рассматриваемом примере присутствует два модуля программы:
- Main.cpp который отвечает не посредственно за само наше приложение — старт, вывод окна на экран, завершение и т.д.
- MainComponent.cpp(.h) который отвечает за наполнение нашего окна — кнопки, фон, поля для ввода текста и т.д.
Стоит заметить что в JUCE все содержимое GUI является классом, наследуемым от класса JUCE Component.
Рассмотрим наш MainComponent.h:
#ifndef __JUCE_HEADER_9002020A4DD09B20__ #define __JUCE_HEADER_9002020A4DD09B20__ //Подключаем наш фреймворк #include "../JuceLibraryCode/JuceHeader.h" //И описываем наш класс class MainComponent : public Component, //Наследуем от основного класса фреймворка public ButtonListener //данный клас отвечает за прослушивание событий кнопок интерфейса
Далее требуется описать поведение класса, его конструкторы и деструкторы.
В секции public находится следующий код:
MainComponent (); ~MainComponent(); void paint (Graphics& g); //метод отвечающий за отрисовку в canvas void resized(); //метод вызываемый при изменении размера void buttonClicked (Button* buttonThatWasClicked); //метод вызываемый при нажатии на кнопку
В секции private находятся непосредственно наши элементы интерфейса:
ScopedPointer<Label> helloWorldLabel; ScopedPointer<TextButton> quitButton; Path internalPath1;
Перейдем непосредственно к логике работы нашего GUI в MainComponent.cpp:
//Не забываем подключить заголовочный файл нашего класса #include "MainComponent.h" //Добовляем логику для конструктора MainComponent::MainComponent () { addAndMakeVisible (helloWorldLabel = new Label (String::empty, "Hello World!")); //Добавляем наш текстовый лэйбл, делаем его видимым и добавляем дополнительные параметры helloWorldLabel->setFont (Font (40.00f, Font::bold)); helloWorldLabel->setJustificationType (Justification::centred); helloWorldLabel->setEditable (false, false, false); helloWorldLabel->setColour (Label::textColourId, Colours::black); helloWorldLabel->setColour (TextEditor::textColourId, Colours::black); helloWorldLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); addAndMakeVisible (quitButton = new TextButton (String::empty)); //То же самое делаем с нашей кнопкой quitButton->setButtonText ("Quit"); quitButton->addListener (this); setSize (600, 300); //Задаем размер нашего содержимого } //Деструктор просто уничтожает содержимое нашего GUI MainComponent::~MainComponent() { helloWorldLabel = nullptr; quitButton = nullptr; } //И описываем все методы нашего класса void MainComponent::paint (Graphics& g) { g.fillAll (Colour (0xffc1d0ff)); g.setColour (Colours::white); g.fillPath (internalPath1); g.setColour (Colour (0xff6f6f6f)); g.strokePath (internalPath1, PathStrokeType (5.200f)); } void MainComponent::resized() { helloWorldLabel->setBounds (152, 80, 296, 48); quitButton->setBounds (getWidth() - 176, getHeight() - 60, 120, 32); internalPath1.clear(); internalPath1.startNewSubPath (136.0f, 80.0f); internalPath1.quadraticTo (176.0f, 24.0f, 328.0f, 32.0f); internalPath1.quadraticTo (472.0f, 40.0f, 472.0f, 104.0f); internalPath1.quadraticTo (472.0f, 192.0f, 232.0f, 176.0f); internalPath1.lineTo (184.0f, 216.0f); internalPath1.lineTo (200.0f, 168.0f); internalPath1.quadraticTo (96.0f, 136.0f, 136.0f, 80.0f); internalPath1.closeSubPath(); } void MainComponent::buttonClicked (Button* buttonThatWasClicked) { if (buttonThatWasClicked == quitButton) { JUCEApplication::quit(); } }
На этом наш класс готов к тому что бы поселиться в окне приложения. Перейдем к Main.cpp и посмотрим каким образом инициализируется и запускается наш пример.
//Поключаем наш фреймворк и класс контента #include "../JuceLibraryCode/JuceHeader.h" #include "MainComponent.h" //Описываем окно нашего приложения class HelloWorldWindow : public DocumentWindow { public: HelloWorldWindow(): DocumentWindow ("JUCE Hello World!", Colours::lightgrey, DocumentWindow::allButtons, true) { // Заполняем окно нашим содержимым setContentOwned (new MainComponent(), true); // Задаем положение по центру centreWithSize (getWidth(), getHeight()); // И отображаем его setVisible (true); } ~HelloWorldWindow() { // Описываем деструктор если он нам нужен } void closeButtonPressed() { // Описываем реакцию на нажатие кнопки закрытия JUCEApplication::quit(); } };
Окно мы описали, теперь очередь за самим приложением:
class JUCEHelloWorldApplication : public JUCEApplication //Наследуем от основного класса приложения JUCE { public: JUCEHelloWorldApplication() {} void initialise (const String& commandLine) { // Инициализируем приложение создавая наше окно helloWorldWindow = new HelloWorldWindow(); } void shutdown() { // Описываем поведение при закрытии приложения helloWorldWindow = nullptr; } //Далее задаются методы для получения некоторой информации о приложении const String getApplicationName() { return "Hello World for JUCE"; } const String getApplicationVersion() { // ProjectInfo::versionString автоматически обновляется Jucer, и // описывается в JuceHeader.h который генерируется для нашего проекта return ProjectInfo::versionString; } bool moreThanOneInstanceAllowed() //Разрешаем запуск нескольких версий { return true; } void anotherInstanceStarted (const String& commandLine) { } private: ScopedPointer<HelloWorldWindow> helloWorldWindow; //свойства класса нашего приложения, по сути все окна которые в нем содержаться // Этот макрос создает точку входа main() нашего приложения. START_JUCE_APPLICATION (JUCEHelloWorldApplication)
Все готово, если наш проект собрать и запустить то мы получаем вот такой результат:

Если вы желаете посмотреть на что еще способен JUCE рекомендую собрать и запустить приложение Demo из папки extras, в котором показаны основные возможности данного фреймворка, но не забывайте что их гораздо больше и все зависит от того как вы примените то что имеете.
Полезные ссылки
- Официальный сайт
- Страница на GitHub
- Страница на Sourceforge
- Официальная страница с документацией
- Juce Programming Tutorial достаточно подробное описание разработки приложения с использованием JUCE
Послесловие
Надеюсь кому то мой экспромт окажется полезным.
Мое личное мнение таково: данный фреймворк заслуживает внимания и того, что бы использоваться в малых и больших проектах.
С удовольствием приму любую критику и замечания, спасибо что обратили внимание на данный пост!
ссылка на оригинал статьи http://habrahabr.ru/post/209956/
Добавить комментарий