Опубликован: 13.07.2012 | Доступ: свободный | Студентов: 461 / 9 | Оценка: 5.00 / 5.00 | Длительность: 18:06:00
Специальности: Программист
Лекция 3:

Компонентная модель Juce. Общие свойства компонентов

< Лекция 2 || Лекция 3 || Лекция 4 >
Аннотация: В этой лекции вы познакомитесь с компонентной моделью Juce, узнаете, что такое компонент содержимого, и как его включать в главное окно программы.

Цель лекции: Получить общие представления о компонентах Juce и их использовании в приложениях

Библиотека Juce написана с помощью современной реализации языка C++ без включения устаревших C-подобных конструкций и основывается на объектно-ориентированной компонентной модели. Это значит, что программа, использующая Juce, состоит из компонентов — независимых модулей программного кода, предназначенных для выполнения определённых функций и повторного использования, подключаемых динамически на этапе выполнения программы. Взаимодействие компонентов Juce осуществляется за счёт слушателей (listeners), которые отслеживают события компонентов (изменение размера, щелчок пользователя в пределах границ компонента и т.п.), которые являются источниками событий.

В соответствии с парадигмой компонентной модели расширение функциональности приложения достигается путём создания новых компонентов на основе существующих. При этом новые компоненты наследуют лишь интерфейсы, но не реализацию ранее созданных. Мы с этим столкнулись в лекции 2, когда создавали класс главного окна нашей программы (TMainForm), унаследовав его от класса DocumentWindow, который, в свою очередь, унаследован от ResizableWindow и Component.

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

В предыдущей лекции мы создали простейшее оконное приложение с изменяемыми размерами и кнопками строки заголовка. Несмотря на то, что практическая ценность этой программы нулевая, она способна реагировать на действия пользователя за счёт класса главного окна TMainForm. Если проследить иерархию нашего класса, то она будет следующей: Component > TopLevelWindow > ResizableWindow > DocumentWindow > TMainForm. Таким образом, в основе класса главного окна лежит класс Component. То же самое можно сказать про любой элемент управления и отображения информации Juce-программы.

Любой компонент может выступать в качестве контейнера для других компонентов. Включение в состав компонента-контейнера дочернего компонента осуществляется с помощью функции void Component::addChildComponent(Component* child, int zOrder = -1), где child — добавляемый компонент, а zOrderиндекс в списке дочерних компонентов, в который будет внедрён новый компонент. В том случае, если индекс равен -1, компонент будет внедрён в начало списка, а если 0, то в его конец.

Заметим, что после добавления в список контейнера дочерний компонент остаётся невидимым, пока не будет вызван его метод setVisible(true). Поэтому удобнее использовать другую функцию, void Component::addAndMakeVisible (Component* child, int zOrder = -1), которая не только добавляет в контейнер дочерний компонент, но и делает последний видимым.

Также заметим, что главное окно приложения обычно включает так называемый главный компонент или компонент содержимого (content component). Он располагается в центре главного окна, окружён его рамкой и определяет внешний вид программы. Обычно компонент содержимого является контейнером для других, дочерних, компонентов.

Вплоть до версии Juce 1.52 его включали в класс главного окна посредством вызова метода void ResizableWindow::setContentComponent(Component* newContentComponent, bool deleteOldOne = true, bool resizeToFit = false), где newContentComponentуказатель на добавляемый в окно компонент содержимого, deleteOldOne — флаг того, следует ли удалить предыдущий компонент содержимого (если он был ранее добавлен). В том случае, если переменная deleteOldOne принимает значение false, то предыдущий компонент содержимого будет исключён из списка дочерних компонентов окна, но занимаемая им память освобождена не будет. Если переменная resizeToFit принимает значение true, то окно будет сохранять свои размеры таким образом, чтобы соответствовать размерам компонента содержимого. В противном случае новый компонент будет растягиваться таким образом, чтобы занять всё доступное пространство окна.

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

Начиная с версии 1.53 в качестве альтернативы setContentComponent предлагается метод void ResizableWindow::setContentOwned(Component* newContentComponent, bool resizeToFitWhenContentChangesSize), который, подобно предыдущему, помещает компонент содержимого в центр главного окна. Функция принимает следующие параметры:

  • newContentComponent — указатель на новый компонент содержимого; при этом компонент, в котором больше нет необходимости, удаляется автоматически;
  • resizeToFitWhenContentChangesSize — флаг необходимости подстраивания размеров главного окна под размер компонента содержимого. Если параметр принимет значение true, при изменении размеров компонента содержимого главное окно изменяется таким образом, чтобы полностью охватывать компонент.

Рассмотрим работу с компонентами на простом примере. В качестве основы возьмём пример из "Начало работы с Juce. Создание приложений. Главное окно" и добавим в класс нашего главного окна TMainForm компонент содержимого — ярлык (класс Label), который будет отображать надпись "Привет, мир!" ( пример 3.1и пример 3.2).

#ifndef _TMainForm_h_
#define _TMainForm_h_
//---------------------------------------------------------------------
#include "../JuceLibraryCode/JuceHeader.h"
//---------------------------------------------------------------------
class TMainForm : public DocumentWindow
{
public:
    TMainForm();
    ~TMainForm();

    void closeButtonPressed();

private:
    // Компонент содержимого
    Label* pHelloLabel;
};
//---------------------------------------------------------------------
#endif
Листинг 3.1. Объявление класса главного окна приложения (файл TMainForm.h)
#include "TMainForm.h"
//---------------------------------------------------------------------
#define tr(s) String::fromUTF8(s)
//---------------------------------------------------------------------
TMainForm::TMainForm() : DocumentWindow(
    JUCEApplication::getInstance()->getApplicationName(),
    Colours::azure,
    DocumentWindow::allButtons)
{
  centreWithSize(400, 200);
  setResizable(true, false);
  setVisible(true);

  // Динамически создаём ярлык
  pHelloLabel = new Label("Hello Label", tr("Привет, мир!"));
  // Задаём размер ярлыка, равный размеру главного окна
  pHelloLabel->setSize(400, 200);
  // Устанавливаем ярлык в качестве компонента содержимого
  setContentOwned(pHelloLabel, true);
  // Устанавливаем размер и гарнитуру шрифта
  pHelloLabel->setFont(Font(38.0000f, Font::bold));
  // Устанавливаем выравнивание текста
  pHelloLabel->setJustificationType(Justification::centred);
  // Запрещаем редактирование текста ярлыка
  pHelloLabel->setEditable(false, false, false);
  // Устанавливаем цвет фона ярлыка
  pHelloLabel->setColour(Label::backgroundColourId, Colours::azure);
  // Устанавливаем цвет текста надписи
  pHelloLabel->setColour(Label::textColourId, Colours::black);
}
//---------------------------------------------------------------------
TMainForm::~TMainForm()
{
}
//---------------------------------------------------------------------
void TMainForm::closeButtonPressed()
{
  JUCEApplication::getInstance()->systemRequestedQuit();
}
//---------------------------------------------------------------------
Листинг 3.2. Реализация класса главного окна приложения (файл TMainForm.cpp

В заголовочном файле TMainForm в закрытой части класса главного окна мы объявили указатель на ярлык (Label* pHelloLabel пример 3.1), который впоследствии установили в качестве главного компонента окна ( пример 3.2). Внешний вид приложения показан на рисунке 3.1 .

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

Рис. 3.1. Приложение Juce, использующее в качестве компонента содержимого главного окна ярлык с надписью

Обратите внимание, что для корректного вывода текста в программе, строка должна передаваться в определённый нами макрос tr(s), который позволяет откомпилировать её в кодировке UTF8 вне зависимости от текущей системной кодировки.

В старых версиях Juce строка передавалась предопределённый макрос T(), который, хотя и был сохранён в версии 1.53 в целях совместимости, но является запрещённым (deprecated). Данный макрос не обеспечивал кроссплатформенность исходных текстов программ, прежде всего из-за проблем, связанных с совместимостью компиляторов (как известно, MS Visual Studio "не понимает" кодировку UTF8).

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

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

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

Компоненты являются источниками событий, которые улавливаются слушателями.

Упражнение

Соберите пример, рассмотренный в лекции. Измените размер шрифта надписи и её цвет, используя предопределённые цвета Juce (зелёный, Colours::green; синий, Colours::blue; красный, Colours::red).

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

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

< Лекция 2 || Лекция 3 || Лекция 4 >