среда, 22 января 2014 г.

[Из песочницы] JUCE — Кроссплатформенный C++ фреймворк для разработки приложений с пользовательским интерфейсом

image

Приветствую хабросообщество!

Наверно каждый кто профессионально разрабатывает ПО или просто увлекается программированием, рано или поздно приходил к необходимости создавать пользовательский интерфейс для своей программы. И если не рассматривать нативные для платформ окружения и языки такие как 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, который просто генерирует на основе ваших манипуляций код на С++ в соответствующий файл исходного кода (который до того был создан при помощи мастера шаблонов), редактор кода, мастер локализации и ряд других достаточно полезных инструментов.


Немного картинок для наглядности
Конфигурация проекта



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

image

Редактор GUI

image

Добавление sourcecode файлов

image


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

image


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

image


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)


Все готово, если наш проект собрать и запустить то мы получаем вот такой результат:

image


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


Полезные ссылки




Послесловие




Надеюсь кому то мой экспромт окажется полезным.

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

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

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

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