Разработка кроссплатформенных приложений с использованием Juce

Начало работы с Juce. Создание приложений. Главное окно

Разбить на страницы
Показывать лекцию целиком

Цель лекции: Научиться создавать платформ-независимые и платформ-зависимые проекты Juce, а также управлять внешним видом главного окна приложения

Ключевые термины

Colour — класс, хранящий информацию о цвете;

DocumentWindow — класс, отвечающий за создание окна с изменяемыми размерами и полосой заголовка;

JUCEApplication — класс приложения Juce;

ResizableWindow — базовый класс для перемещаемых окон;

START_JUCE_APPLICATION — макрос, осуществляющий запуск приложений Juce.

Организация рабочего места

"Установка" Juce заключается в том, чтобы поместить папку с откомпилированной библиотекой (папка juce) в каталог, где будут находиться проекты ваших программ. В случае версии 2.0 библиотеки не требуется даже компиляция.

Для каждого нового проекта целесообразно создавать отдельный каталог. Для облегчения работы имеет смысл перенести программы Introjucer и the jucer из каталогов, где они были собраны, в каталог проектов.

Структура программы, использующей библиотеку Juce

Запуск программы, написанной с использованием Juce, осуществляет макрос ):

// TApplication — класс, унаследованный от JUCEApplication
#include "TApplication.h"
//---------------------------------------------------------------------
// Этот макрос заменяет функцию main
START_JUCE_APPLICATION(TApplication)
//---------------------------------------------------------------------

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

  • virtual void JUCEApplication::initialise(const String commandLineParameters);
  • virtual void JUCEApplication::shutdown().
  • Кроме того, переопределяются следующие методы:

  • virtual void JUCEApplication::systemRequestedQuit() — вызывается в момент, когда операционная система пытается завершить работу приложения и совершает действия, определённые программистом, которые должна выполнить программа перед закрытием;
  • virtual const String JUCEApplication::getApplicationName() — возвращает имя приложения;
  • virtual const String JUCEApplication::getApplicationVersion() — возвращает версию приложения;
  • virtual bool JUCEApplication::moreThanOneInstanceAllowed() — определяет, возможен ли запуск более чем одного экземпляра приложения.
  • В листингах 2.2 и 2.3 показан простейший пример класса TApplication, объект которого отображает окно класса TMainForm:

    #ifndef _TApplication_h_
    #define _TApplication_h_
    //---------------------------------------------------------------------
    // Автоматически генерируемый файл, содержащий объявления классов Juce
    #include "../JuceLibraryCode/JuceHeader.h"
    //---------------------------------------------------------------------
    class TMainForm; // Класс главного окна
    //---------------------------------------------------------------------
    class TApplication : public JUCEApplication
    {
    public:
        TApplication();
        ~TApplication();
    
        void initialise(const String);
        void shutdown();
        void systemRequestedQuit();
        const String getApplicationName();
        const String getApplicationVersion();
        bool moreThanOneInstanceAllowed();
    
    private:
        TMainForm* pMainWindow; // Главное окно приложения
    };
    //---------------------------------------------------------------------
    #endif
    
    #include "TApplication.h"
    #include "TMainForm.h"
    //---------------------------------------------------------------------
    TApplication::TApplication() : pMainWindow(0)
    {
    }
    //---------------------------------------------------------------------
    TApplication::~TApplication()
    {
    }
    //---------------------------------------------------------------------
    void TApplication::initialise(const String sCommandLine)
    {
        pMainWindow = new TMainForm(); // Создаём главное окно программы
    }
    //---------------------------------------------------------------------
    void TApplication::shutdown()
    {
        if(pMainWindow != 0) delete pMainWindow;
    }
    //---------------------------------------------------------------------
    void TApplication::systemRequestedQuit()
    {
        quit(); // Завершаем работу приложения
    }
    //---------------------------------------------------------------------
    const String TApplication::getApplicationName()
    {
        // Задаём имя приложения 
        // (будет отображаться в заголовке главного окна)
        return "Juce Window Demo";
    }
    //---------------------------------------------------------------------
    const String TApplication::getApplicationVersion()
    {
        // Получаем версию приложения из опций проекта
        return ProjectInfo::versionString;
    }
    //---------------------------------------------------------------------
    bool TApplication::moreThanOneInstanceAllowed()
    {
        // Запрещаем запуск более одного экземпляра приложения
        return false;
    }
    //---------------------------------------------------------------------
    

    Метод initialise() вызывается при запуске приложения и, после выполнения действий, определённых пользователем (в нашем случае это создание главного окна), запускает цикл событий приложения (event-dispatch loop), который отслеживает их вплоть до тех пор, пока не будет вызван метод static void JUCEApplication::quit(), который убивает цикл и завершает работу программы.

    Как видно из листинга 2.3 , окно программы создаётся динамически, и программист должен сам позаботиться о его уничтожении в методе shutdown().

    Как упоминалось выше, метод ).

    Метод getApplicationName() возвращает строку — имя приложения. Именно эта строка отображается в заголовке главного окна.

    Метод ), либо взято из опций проекта Introjucer (о работе с проектом будет сказано ниже).

    const String TApplication::getApplicationVersion()
    {
        return "1.0";
    }
    

    В том случае, если метод moreThanOneInstanceAllowed() возвращает true, при повторном щелчке по значку программы запустится ещё один её экземпляр; в случае, если метод возвращает false, может быть запущен только один экземпляр приложения.

    Основным классом ).

    #ifndef _TMainForm_h_
    #define _TMainForm_h_
    //---------------------------------------------------------------------
    #include "../JuceLibraryCode/JuceHeader.h"
    //---------------------------------------------------------------------
    class TMainForm : public DocumentWindow
    {
    public:
        TMainForm();
        ~TMainForm();
    
        void closeButtonPressed();
    };
    //---------------------------------------------------------------------
    #endif
    
    #include "TMainForm.h"
    //---------------------------------------------------------------------
    TMainForm::TMainForm() : DocumentWindow(
            JUCEApplication::getInstance()->getApplicationName(),
            Colours::azure,
            DocumentWindow::allButtons)
    {
        centreWithSize(400, 200);
        setResizable(true, false);
        setVisible(true);
    }
    //---------------------------------------------------------------------
    TMainForm::~TMainForm()
    {
    }
    //---------------------------------------------------------------------
    void TMainForm::closeButtonPressed()
    {
        JUCEApplication::getInstance()->systemRequestedQuit();
    }
    //---------------------------------------------------------------------
    

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

    В нашем классе () с помощью статического метода static JUCEApplication* JUCEApplication::getInstance() throw() мы получаем ссылку на экземпляр приложения и вызываем метод его getApplicationName(), возвращаующий строку — название программы.

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

    Третий параметр конструктора класса ):

    enum TitleBarButtons
    {
        minimiseButton = 1, 
        maximiseButton = 2, 
        closeButton = 4, 
        allButtons = 7
    }
    

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

    #include "TMainForm.h"
    //---------------------------------------------------------------------
    TMainForm::TMainForm() : DocumentWindow(
            JUCEApplication::getInstance()->getApplicationName(),
            Colours::azure,
            DocumentWindow::minimiseButton | DocumentWindow::closeButton)
    {
        centreWithSize(400, 200);
        // Запрещаем изменение размеров окна посредством растягивания мышью
        setResizable(false, false);
        setVisible(true);
    }
    //---------------------------------------------------------------------
    

    Внешний вид такого окна представлен на рисунке 2.1 .

    (рис 2.1) Окно с неизменяемыми размерами (в строку заголовка включены кнопки "свернуть окно" и "закрыть окно")

    Заметим, что число кнопок заголовка окна (а также их положение) можно изменить вызовом метода , рис 2.2).

    #include "TMainForm.h"
    //---------------------------------------------------------------------
    TMainForm::TMainForm() : DocumentWindow(
            JUCEApplication::getInstance()->getApplicationName(),
            Colours::azure,
            DocumentWindow::allButtons)
    {
        centreWithSize(400, 200);
        // Запрещаем изменение размеров окна посредством растягивания мышью
        setResizable(false, false);
        setTitleBarButtonsRequired(minimiseButton | DocumentWindow::closeButton,
                                   true);
        setVisible(true);
    }
    //---------------------------------------------------------------------
    
    (рис 2.2) Окно с атипичным расположением кнопок заголовка

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

    Класс ) мы вызываем следующие методы, унаследованные от этих классов:

  • void Component::centreWithSize(int width, int height) — задаёт линейные размеры компонента (ширина и длина) и помещает его в центре родительского компонента. В том случае, когда родительского компонента нет (наш случай), окно помещается в центр рабочего стола.
  • void ResizableWindow::setResizable(bool shouldBeResizable, bool useBottomRightCornerResizer) — в зависимости от принимаемых параметров показывает, может ли пользователь изменять размеры окна потягиванием мыши (да, если shouldBeResizable принимаент значение true) и следует ли отображать виджет-ресайзер в правом нижнем углу окна (если виджет отображается, то пользователь может изменять размеры окна посредством потягивания мышью за него, но не за границу окна).

    Вид окна, в котором все параметры принимают значения true, показан на рисунке 2.3 .

    (рис 2.3) Окно с изменяемыми размерами (размеры изменяются с помощью специального виджета в его правом нижнем углу
  • virtual void Component::setVisible(bool shouldBeVisible) — в случае, если аргумент принимает значение true, метод делает окно видимым и доступным для манипуляций пользователя.
  • В заключение отметим, что по умолчанию текст заголовка окна ориентирован по центру. В том случае, если мы хотим, чтобы он был выровнен по левому краю, необходимо в конструкторе класса окна вызвать метод )

    (рис 2.4) Приложение Juce с выравниванием заголовка окна по левому краю

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

    В Juce, как и в других кроссплатформенных библиотеках, существует два типа проектов: платформ-независимый (имеет расширение *.jucer и представляет собой XML-файл) и платформ-зависимые (для Linux это Makefile, для Windows — проекты Visual Studio и т.п.), которые генерируются программой Introjucer (см. лекцию 1) на основе платформ-независимого проекта. Последний также создаётся в программе Introjucer.

    Рассмотрим создание проектов и сборку приложения, использующего Juce версии 1.53, на примере оконного приложения, описанного выше. Создание проекта с помощью Introjucer, входящего в поставку 2-й версии, рассмотрено в конце данной лекции.

    Создайте в папке ваших проектов каталог ), ), ), ) и ).

    Запустите программу Introjucer: в Linux из каталога <каталог Juce>/juce/extras/Introjucer/Builds/Linux/build; в Windows — из каталога <каталог Juce>/juce/extras/Introjucer/Builds/VisualStudio2010/Release.

    Выберите в меню программы )

    (рис 2.5) Диалоговое окно New Juce Project

    Появится диалоговое окно выбора каталога для сохранения файлов проекта. Выделите в нём созданную ранее папку JuceWindow и нажмите кнопку Open. В появившемся диалоговом окне New GUI Application в поле Project Name введите название проекта, а в выпадающем списке Files to Auto-Generate выберите Don't create any files (хотя по умолчанию ).

    (рис 2.6) Диалоговое окно New GUI Application

    Будет создан новый проект Juce. На вкладке Project Settings будут отображены основные свойства проекта: Project Name (название проекта), Project Version (его версия), Project Type (тип проекта; в нашем случае это приложение с графическим интерфейсом пользователя – Application (GUI)), Bundle Identifier (строка – идентификатор приложения). Последняя необходима для однозначной характеристики создаваемого приложения в Mac OS X и iPhone. Строка должна соответствовать нотации Reverse-DNS и состоять из двух частей: названия компании разработчика (по умолчанию стоит ). Следует помнить, что строка не должна содержать символа "*".

    (рис 2.7) Проект Juce (Introjucer для Juce 1.53; добавлены исходные тексты программы)

    В окне ).

    (рис 2.8) Просмотр исходных текстов программы в Introjucer

    Выберите в меню File > Save Project. В папке JuceWindow будет сохранён Xml-файл платформ-независимого проекта JuceWindow.jucer (в последующем его можно редактировать в Introjucer, выбрав в меню File > Open...), папка JuceLibraryCode, в которой содержится необходимый для работы приложения код (ранее мы его включили в исходные тексты нашей программы директивой #include "../JuceLibraryCode/JuceHeader.h"), а также папка Builds, которая содержит подпапки платформ-зависимых проектов; по умолчанию это iOS (сборка приложения для iPhone), MacOSX (сборка приложения для Mac OS X), MSVC6 (сборка приложения для Windows в среде Visual C++ 6), VisualStudio2005 (сборка приложения для Windows в среде Visual C++ 2005), VisualStudio2008 (сборка приложения для Windows в среде Visual C++ 2008), VisualStudio2010 (сборка приложения для Windows в среде Visual C++ 2010).

    На момент написания книги Introjucer из Juce версии 1.53 не включал по умолчанию в проект экспортёр для автоматической генерации Linux Makefile.

    Это можно исправить следующим образом: нажать на кнопку ) и выбрать в меню Create New Export Target > Create a new Linux Makefile Target.

    Кроме того, можно отредактировать проект вручную, для чего открыть файл *.jucer с помощью любого текстового редактора (например, KWrite) и добавить в секцию <EXPORTFORMATS> следующую строку:

    <LINUX_MAKE targetFolder="Builds/Linux" vstFolder="~/SDKs/vstsdk2.4" juceFolder="..\juce"/>
    

    После добавления экспортёра тем или иным способом открытый в Introjucer платформ-независимый проект следует сохранить (выберите в меню File > Save Project). В папке Builds появится подпапка Linux, содержащая сгенерированный Makefile, а также другие платформ-зависимые проекты соответственно добавленным экспортёрам.

    Если вы планируете осуществлять сборку программы для Windows только в одной среде (наример, Visual Studio 2008), вы можете удалить ненужные экспортёры, нажав кнопку "Add/Remove Exporters..." в нижней части окна Introjucer и выбрать в меню Remove Export target, после чего отметить платформ-зависимый проект, который вы не намерены исользовать.

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

    Особенности Juce 2.0

    Создание проекта для ).

    (рис 2.9) Выбор опций проекта в Introjucer, входящем в поставку Juce 2.0

    Необходимо ввести название проекта в поле ).

    После нажатия на кнопку ). Интересно, что в обеих версиях Juce номера версий Introjucer совпадают (3.0.0), хотя это по сути разные программы.

    (рис 2.10) Проект Juce (Introjucer для Juce 2.0; исходные тексты программы ещё не добавлены)

    Работа с проектом мало отличается от таковой в Introjucer для Juce1.53. Основное отличие — выбор модулей библиотеки для компиляции. Для базового проекта без поддержки воспроизведения аудио достаточно включить модули ).

    Выделив тот или иной модуль, включаемый в нашу программу, можно отредактировать его опции. Так, целесообразно в модуле juce_graphics сделать недоступной (Disabled) опцию JUCE_USE_DIRECTWRITE. Это необходимо для того, чтобы обеспечить беспроблемную сборку проектов в Windows, не имеющих инструментов разработки с использованием DirectX.

    В отличие от старого Introjucer, новый не создаёт автоматически платформ-зависимые проекты. Для их генерации нажмите кнопку "Add a New Exporter..." и выберите в выпадающем списке нужную платформу. После этого достаточно сохранить проект.

    Краткие итоги

    Для создания минимального приложения Juce необходимо написать класс, наследующий JUCEApplication. Этот класс принимается в качестве параметра макросом START_JUCE_APPLICATION, отвечающим за запуск программы. Основой оконного приложения Juce является класс, наследующий DocumentWindow. Параметры конструктора класса позволяют изменять внешний вид окна (положение надписи в заголовке, кнопки полосы заголовка, цвет окна и т.п.).

    Упражнение

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

    Дополнительные материалы

    Архив с исходными текстами примера Вы можете скачать здесь

    Страницы:

    Цель лекции: Научиться создавать платформ-независимые и платформ-зависимые проекты Juce, а также управлять внешним видом главного окна приложения

    Ключевые термины

    Colour — класс, хранящий информацию о цвете;

    DocumentWindow — класс, отвечающий за создание окна с изменяемыми размерами и полосой заголовка;

    JUCEApplication — класс приложения Juce;

    ResizableWindow — базовый класс для перемещаемых окон;

    START_JUCE_APPLICATION — макрос, осуществляющий запуск приложений Juce.

    Организация рабочего места

    "Установка" Juce заключается в том, чтобы поместить папку с откомпилированной библиотекой (папка juce) в каталог, где будут находиться проекты ваших программ. В случае версии 2.0 библиотеки не требуется даже компиляция.

    Для каждого нового проекта целесообразно создавать отдельный каталог. Для облегчения работы имеет смысл перенести программы Introjucer и the jucer из каталогов, где они были собраны, в каталог проектов.

    Структура программы, использующей библиотеку Juce

    Запуск программы, написанной с использованием Juce, осуществляет макрос ):

    // TApplication — класс, унаследованный от JUCEApplication
    #include "TApplication.h"
    //---------------------------------------------------------------------
    // Этот макрос заменяет функцию main
    START_JUCE_APPLICATION(TApplication)
    //---------------------------------------------------------------------
    

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

  • virtual void JUCEApplication::initialise(const String commandLineParameters);
  • virtual void JUCEApplication::shutdown().
  • Кроме того, переопределяются следующие методы:

  • virtual void JUCEApplication::systemRequestedQuit() — вызывается в момент, когда операционная система пытается завершить работу приложения и совершает действия, определённые программистом, которые должна выполнить программа перед закрытием;
  • virtual const String JUCEApplication::getApplicationName() — возвращает имя приложения;
  • virtual const String JUCEApplication::getApplicationVersion() — возвращает версию приложения;
  • virtual bool JUCEApplication::moreThanOneInstanceAllowed() — определяет, возможен ли запуск более чем одного экземпляра приложения.
  • В листингах 2.2 и 2.3 показан простейший пример класса TApplication, объект которого отображает окно класса TMainForm:

    #ifndef _TApplication_h_
    #define _TApplication_h_
    //---------------------------------------------------------------------
    // Автоматически генерируемый файл, содержащий объявления классов Juce
    #include "../JuceLibraryCode/JuceHeader.h"
    //---------------------------------------------------------------------
    class TMainForm; // Класс главного окна
    //---------------------------------------------------------------------
    class TApplication : public JUCEApplication
    {
    public:
        TApplication();
        ~TApplication();
    
        void initialise(const String);
        void shutdown();
        void systemRequestedQuit();
        const String getApplicationName();
        const String getApplicationVersion();
        bool moreThanOneInstanceAllowed();
    
    private:
        TMainForm* pMainWindow; // Главное окно приложения
    };
    //---------------------------------------------------------------------
    #endif
    
    #include "TApplication.h"
    #include "TMainForm.h"
    //---------------------------------------------------------------------
    TApplication::TApplication() : pMainWindow(0)
    {
    }
    //---------------------------------------------------------------------
    TApplication::~TApplication()
    {
    }
    //---------------------------------------------------------------------
    void TApplication::initialise(const String sCommandLine)
    {
        pMainWindow = new TMainForm(); // Создаём главное окно программы
    }
    //---------------------------------------------------------------------
    void TApplication::shutdown()
    {
        if(pMainWindow != 0) delete pMainWindow;
    }
    //---------------------------------------------------------------------
    void TApplication::systemRequestedQuit()
    {
        quit(); // Завершаем работу приложения
    }
    //---------------------------------------------------------------------
    const String TApplication::getApplicationName()
    {
        // Задаём имя приложения 
        // (будет отображаться в заголовке главного окна)
        return "Juce Window Demo";
    }
    //---------------------------------------------------------------------
    const String TApplication::getApplicationVersion()
    {
        // Получаем версию приложения из опций проекта
        return ProjectInfo::versionString;
    }
    //---------------------------------------------------------------------
    bool TApplication::moreThanOneInstanceAllowed()
    {
        // Запрещаем запуск более одного экземпляра приложения
        return false;
    }
    //---------------------------------------------------------------------
    

    Метод initialise() вызывается при запуске приложения и, после выполнения действий, определённых пользователем (в нашем случае это создание главного окна), запускает цикл событий приложения (event-dispatch loop), который отслеживает их вплоть до тех пор, пока не будет вызван метод static void JUCEApplication::quit(), который убивает цикл и завершает работу программы.

    Как видно из листинга 2.3 , окно программы создаётся динамически, и программист должен сам позаботиться о его уничтожении в методе shutdown().

    Как упоминалось выше, метод ).

    Метод getApplicationName() возвращает строку — имя приложения. Именно эта строка отображается в заголовке главного окна.

    Метод ), либо взято из опций проекта Introjucer (о работе с проектом будет сказано ниже).

    const String TApplication::getApplicationVersion()
    {
        return "1.0";
    }
    

    В том случае, если метод moreThanOneInstanceAllowed() возвращает true, при повторном щелчке по значку программы запустится ещё один её экземпляр; в случае, если метод возвращает false, может быть запущен только один экземпляр приложения.

    Основным классом ).

    #ifndef _TMainForm_h_
    #define _TMainForm_h_
    //---------------------------------------------------------------------
    #include "../JuceLibraryCode/JuceHeader.h"
    //---------------------------------------------------------------------
    class TMainForm : public DocumentWindow
    {
    public:
        TMainForm();
        ~TMainForm();
    
        void closeButtonPressed();
    };
    //---------------------------------------------------------------------
    #endif
    
    #include "TMainForm.h"
    //---------------------------------------------------------------------
    TMainForm::TMainForm() : DocumentWindow(
            JUCEApplication::getInstance()->getApplicationName(),
            Colours::azure,
            DocumentWindow::allButtons)
    {
        centreWithSize(400, 200);
        setResizable(true, false);
        setVisible(true);
    }
    //---------------------------------------------------------------------
    TMainForm::~TMainForm()
    {
    }
    //---------------------------------------------------------------------
    void TMainForm::closeButtonPressed()
    {
        JUCEApplication::getInstance()->systemRequestedQuit();
    }
    //---------------------------------------------------------------------
    

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

    В нашем классе () с помощью статического метода static JUCEApplication* JUCEApplication::getInstance() throw() мы получаем ссылку на экземпляр приложения и вызываем метод его getApplicationName(), возвращаующий строку — название программы.

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

    Третий параметр конструктора класса ):

    enum TitleBarButtons
    {
        minimiseButton = 1, 
        maximiseButton = 2, 
        closeButton = 4, 
        allButtons = 7
    }
    

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

    #include "TMainForm.h"
    //---------------------------------------------------------------------
    TMainForm::TMainForm() : DocumentWindow(
            JUCEApplication::getInstance()->getApplicationName(),
            Colours::azure,
            DocumentWindow::minimiseButton | DocumentWindow::closeButton)
    {
        centreWithSize(400, 200);
        // Запрещаем изменение размеров окна посредством растягивания мышью
        setResizable(false, false);
        setVisible(true);
    }
    //---------------------------------------------------------------------
    

    Внешний вид такого окна представлен на рисунке 2.1 .

    (рис 2.1) Окно с неизменяемыми размерами (в строку заголовка включены кнопки "свернуть окно" и "закрыть окно")

    Заметим, что число кнопок заголовка окна (а также их положение) можно изменить вызовом метода , рис 2.2).

    #include "TMainForm.h"
    //---------------------------------------------------------------------
    TMainForm::TMainForm() : DocumentWindow(
            JUCEApplication::getInstance()->getApplicationName(),
            Colours::azure,
            DocumentWindow::allButtons)
    {
        centreWithSize(400, 200);
        // Запрещаем изменение размеров окна посредством растягивания мышью
        setResizable(false, false);
        setTitleBarButtonsRequired(minimiseButton | DocumentWindow::closeButton,
                                   true);
        setVisible(true);
    }
    //---------------------------------------------------------------------
    
    (рис 2.2) Окно с атипичным расположением кнопок заголовка

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

    Класс ) мы вызываем следующие методы, унаследованные от этих классов:

  • void Component::centreWithSize(int width, int height) — задаёт линейные размеры компонента (ширина и длина) и помещает его в центре родительского компонента. В том случае, когда родительского компонента нет (наш случай), окно помещается в центр рабочего стола.
  • void ResizableWindow::setResizable(bool shouldBeResizable, bool useBottomRightCornerResizer) — в зависимости от принимаемых параметров показывает, может ли пользователь изменять размеры окна потягиванием мыши (да, если shouldBeResizable принимаент значение true) и следует ли отображать виджет-ресайзер в правом нижнем углу окна (если виджет отображается, то пользователь может изменять размеры окна посредством потягивания мышью за него, но не за границу окна).

    Вид окна, в котором все параметры принимают значения true, показан на рисунке 2.3 .

    (рис 2.3) Окно с изменяемыми размерами (размеры изменяются с помощью специального виджета в его правом нижнем углу
  • virtual void Component::setVisible(bool shouldBeVisible) — в случае, если аргумент принимает значение true, метод делает окно видимым и доступным для манипуляций пользователя.
  • В заключение отметим, что по умолчанию текст заголовка окна ориентирован по центру. В том случае, если мы хотим, чтобы он был выровнен по левому краю, необходимо в конструкторе класса окна вызвать метод )

    (рис 2.4) Приложение Juce с выравниванием заголовка окна по левому краю

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

    В Juce, как и в других кроссплатформенных библиотеках, существует два типа проектов: платформ-независимый (имеет расширение *.jucer и представляет собой XML-файл) и платформ-зависимые (для Linux это Makefile, для Windows — проекты Visual Studio и т.п.), которые генерируются программой Introjucer (см. лекцию 1) на основе платформ-независимого проекта. Последний также создаётся в программе Introjucer.

    Рассмотрим создание проектов и сборку приложения, использующего Juce версии 1.53, на примере оконного приложения, описанного выше. Создание проекта с помощью Introjucer, входящего в поставку 2-й версии, рассмотрено в конце данной лекции.

    Создайте в папке ваших проектов каталог ), ), ), ) и ).

    Запустите программу Introjucer: в Linux из каталога <каталог Juce>/juce/extras/Introjucer/Builds/Linux/build; в Windows — из каталога <каталог Juce>/juce/extras/Introjucer/Builds/VisualStudio2010/Release.

    Выберите в меню программы )

    (рис 2.5) Диалоговое окно New Juce Project

    Появится диалоговое окно выбора каталога для сохранения файлов проекта. Выделите в нём созданную ранее папку JuceWindow и нажмите кнопку Open. В появившемся диалоговом окне New GUI Application в поле Project Name введите название проекта, а в выпадающем списке Files to Auto-Generate выберите Don't create any files (хотя по умолчанию ).

    (рис 2.6) Диалоговое окно New GUI Application

    Будет создан новый проект Juce. На вкладке Project Settings будут отображены основные свойства проекта: Project Name (название проекта), Project Version (его версия), Project Type (тип проекта; в нашем случае это приложение с графическим интерфейсом пользователя – Application (GUI)), Bundle Identifier (строка – идентификатор приложения). Последняя необходима для однозначной характеристики создаваемого приложения в Mac OS X и iPhone. Строка должна соответствовать нотации Reverse-DNS и состоять из двух частей: названия компании разработчика (по умолчанию стоит ). Следует помнить, что строка не должна содержать символа "*".

    (рис 2.7) Проект Juce (Introjucer для Juce 1.53; добавлены исходные тексты программы)

    В окне ).

    (рис 2.8) Просмотр исходных текстов программы в Introjucer

    Выберите в меню File > Save Project. В папке JuceWindow будет сохранён Xml-файл платформ-независимого проекта JuceWindow.jucer (в последующем его можно редактировать в Introjucer, выбрав в меню File > Open...), папка JuceLibraryCode, в которой содержится необходимый для работы приложения код (ранее мы его включили в исходные тексты нашей программы директивой #include "../JuceLibraryCode/JuceHeader.h"), а также папка Builds, которая содержит подпапки платформ-зависимых проектов; по умолчанию это iOS (сборка приложения для iPhone), MacOSX (сборка приложения для Mac OS X), MSVC6 (сборка приложения для Windows в среде Visual C++ 6), VisualStudio2005 (сборка приложения для Windows в среде Visual C++ 2005), VisualStudio2008 (сборка приложения для Windows в среде Visual C++ 2008), VisualStudio2010 (сборка приложения для Windows в среде Visual C++ 2010).

    На момент написания книги Introjucer из Juce версии 1.53 не включал по умолчанию в проект экспортёр для автоматической генерации Linux Makefile.

    Это можно исправить следующим образом: нажать на кнопку ) и выбрать в меню Create New Export Target > Create a new Linux Makefile Target.

    Кроме того, можно отредактировать проект вручную, для чего открыть файл *.jucer с помощью любого текстового редактора (например, KWrite) и добавить в секцию <EXPORTFORMATS> следующую строку:

    <LINUX_MAKE targetFolder="Builds/Linux" vstFolder="~/SDKs/vstsdk2.4" juceFolder="..\juce"/>
    

    После добавления экспортёра тем или иным способом открытый в Introjucer платформ-независимый проект следует сохранить (выберите в меню File > Save Project). В папке Builds появится подпапка Linux, содержащая сгенерированный Makefile, а также другие платформ-зависимые проекты соответственно добавленным экспортёрам.

    Если вы планируете осуществлять сборку программы для Windows только в одной среде (наример, Visual Studio 2008), вы можете удалить ненужные экспортёры, нажав кнопку "Add/Remove Exporters..." в нижней части окна Introjucer и выбрать в меню Remove Export target, после чего отметить платформ-зависимый проект, который вы не намерены исользовать.

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

    Особенности Juce 2.0

    Создание проекта для ).

    (рис 2.9) Выбор опций проекта в Introjucer, входящем в поставку Juce 2.0

    Необходимо ввести название проекта в поле ).

    После нажатия на кнопку ). Интересно, что в обеих версиях Juce номера версий Introjucer совпадают (3.0.0), хотя это по сути разные программы.

    (рис 2.10) Проект Juce (Introjucer для Juce 2.0; исходные тексты программы ещё не добавлены)

    Работа с проектом мало отличается от таковой в Introjucer для Juce1.53. Основное отличие — выбор модулей библиотеки для компиляции. Для базового проекта без поддержки воспроизведения аудио достаточно включить модули ).

    Выделив тот или иной модуль, включаемый в нашу программу, можно отредактировать его опции. Так, целесообразно в модуле juce_graphics сделать недоступной (Disabled) опцию JUCE_USE_DIRECTWRITE. Это необходимо для того, чтобы обеспечить беспроблемную сборку проектов в Windows, не имеющих инструментов разработки с использованием DirectX.

    В отличие от старого Introjucer, новый не создаёт автоматически платформ-зависимые проекты. Для их генерации нажмите кнопку "Add a New Exporter..." и выберите в выпадающем списке нужную платформу. После этого достаточно сохранить проект.

    Краткие итоги

    Для создания минимального приложения Juce необходимо написать класс, наследующий JUCEApplication. Этот класс принимается в качестве параметра макросом START_JUCE_APPLICATION, отвечающим за запуск программы. Основой оконного приложения Juce является класс, наследующий DocumentWindow. Параметры конструктора класса позволяют изменять внешний вид окна (положение надписи в заголовке, кнопки полосы заголовка, цвет окна и т.п.).

    Упражнение

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

    Дополнительные материалы

    Архив с исходными текстами примера Вы можете скачать здесь

    Вернуться к учебному плану