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

Элементы управления. Компоненты панели инструментов

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

Цель лекции: Научиться создавать и использовать панели инструментов в своих программах

Для построения панели инструментов библиотека Juce предоставляет классы Toolbar, ToolbarItemFactory и ToolbarButton.

Toolbar — компонент, который рисует вертикальную или горизонтальную полосу (панель), содержащую кнопки или иные виджеты в порядке, определяемом ToolbarItcodeFactory.

ToolbarItemFactory отвечает за создание и добавление на панель инструментов её элементов. Каждый тип добавляемых элементов должен характеризоваться уникальным номером (ID), включая разделители и распорки.

ToolbarButton — "быстрая" кнопка инструментальной панели, наиболее часто добавляемый на неё виджет. Этот тип кнопок отличается тем, что содержит вместо надписи небольшое изображение (пиктограмму, icon), символизирующее определённую команду меню.

Класс ToolbarButton является потомком ToolbarItemComponent, с помощью которого можно создавать произвольные виджеты для добавления на панель инструментов.

Программа, окно которой показано на рисунке 14.1 , демонстрирует применение всех вышеперечисленных классов.

(рис 14.1) Программа, демонстрирующая работу панели инструментов

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

Как упоминалось, за создание кнопок панели инструментов отвечает класс ToolbarItemFactory. Он является абстрактным и включает три чистые виртуальные функции:

  • virtual void ToolbarItemFactory::getAllToolbarItemIds(Array<int> ids) — задаёт массив уникальных числовых не равных нулю идентификаторов (ID) для каждого из типов элементов, которые может создавать ToolbarItemFactory;
  • virtual void ToolbarItemFactory::getDefaultItemSet(Array<int> ids) — задаёт собственно сам набор добавляемых на панель инструментов элементов, основываясь на наборе идентификаторов, созданных предыдущей функцией;
  • virtual ToolbarItemComponent* ToolbarItemFactory::createItem(int itemId) — создаёт компонент (например, кнопку), добавляемый на панель инструментов, из числа набора, основываясь на наборе идентификаторов, созданных предыдущей функцией.
  • Объявим собственный класс, , ).

    #ifndef _TTolbarFactory_h_
    #define _TTolbarFactory_h_
    //-----------------------------------------------
    #include "../JuceLibraryCode/JuceHeader.h"
    //------------------------------------------------
    // "Фабрика" для создания кнопок панели инструментов
    class TToolbarFactory : public ToolbarItemFactory
    {
    public:
      TToolbarFactory();
      ~TToolbarFactory();
    
      // Идентификаторы создаваемых кнопок
      enum TToolbarItemID
      {
        FileNew = 1,
        FileOpen = 2,
        FileQuit = 3,
        ViewOrientation = 4
      };
    
      // Задаёт идентификаторы кнопок
      void getAllToolbarItemIds(Array<int>);
      // Задаёт набор кнопок панели инструментов 
      void getDefaultItemSet(Array<int>);
      // Создаёт элемент панели инструментов
      ToolbarItemComponent* createItem(int);
    
      // Кнопка "Выход"
      ToolbarButton* pFileQuitButton;
      // Кнопка "Новый"
      ToolbarButton* pFileNewButton;
      // Кнопка "Открыть"
      ToolbarButton* pFileOpenButton;
      // Кнопка "Ориентация"
      ToolbarButton* pViewOrientationButton;
    
    private:
      // Изображения - пиктограммы кнопок
      Image ImageExit_png;
      Image ImageNew_png;
      Image ImageOpen_png;
      Image ImageSwitch_png;
    };
    //-----------------------------------------
    #endif
    

    В качестве члена класса мы создали перечислимый список TToolbarItemID идентификаторов кнопок (в принципе, его можно объявить и вне класса, например, если вы хотите использовать один набор идентификаторов команд для кнопок панели инструментов и пунктов меню). В качестве открытых членов класса мы объявили указатели на кнопки — элементы панели инструментов, а закрытых — добавляемые на их поверхность изображения (класс Image).

    Рассмотрим реализацию нашего класса . В большей своей части она состоит из реализации вышеупомянутых чистых виртуальных функций getAllToolbarItemIds, getDefaultItemSet и createItem.

    #include "TToolbarFactory.h"
    // Подключаем бинарные ресурсы изображений
    #include "TImagesFactory.h"
    //--------------------------------------
    TToolbarFactory::TToolbarFactory()
    {
      // Загружаем изображения в объекты класса Image из памяти
      ImageExit_png = ImageCache::getFromMemory(TImagesFactory::psExit_png,
                  TImagesFactory::iExit_pngSize);
      ImageNew_png = ImageCache::getFromMemory(TImagesFactory::psNew_png, 
                  TImagesFactory::iNew_pngSize);
      ImageOpen_png = ImageCache::getFromMemory(TImagesFactory::psOpen_png, 
                  TImagesFactory::iOpen_pngSize);
      ImageSwitch_png = ImageCache::getFromMemory(TImagesFactory::psRotate_png, 
                  TImagesFactory::iRotate_pngSize);
    }
    //--------------------------------------
    TToolbarFactory::~TToolbarFactory()
    {
    }
    //----------------------------------------
    void TToolbarFactory::getAllToolbarItemIds(Array<int> iIDs)
    {
      // Задаём список идентификаторов элементов панели инструментов: 
      // кнопок, разделителей (separators) и распорок (spacers)
      iIDs.add(FileNew);
      iIDs.add(FileOpen);
      iIDs.add(FileQuit);
      iIDs.add(ViewOrientation);
      iIDs.add(spacerId);
      iIDs.add(separatorBarId);
    }
    //-------------------------------------------
    void TToolbarFactory::getDefaultItemSet(Array<int> iIDs)
    {
      // Определяем порядок добавления элементов на инструментальную панель
      iIDs.add(FileQuit);
      iIDs.add(separatorBarId);
      iIDs.add(FileNew);
      iIDs.add(FileOpen);
      iIDs.add(separatorBarId);
      iIDs.add(ViewOrientation);
    }
    //----------------------------------------------
    ToolbarItemComponent* TToolbarFactory::createItem(int iItemID)
    {
      switch(iItemID)
      {
        // Создаём кнопки панели инструментов, "привязывая" их 
        // к ранее созданным идентификаторам
        case FileQuit:
        {
            pFileQuitButton = new ToolbarButton(iItemID, "Quit", 
                Drawable::createFromImageData(
                TImagesFactory::psExit_png, 
                TImagesFactory::iExit_pngSize),
              0);
            return pFileQuitButton;
          }
          case FileNew:
          {
          pFileNewButton = new ToolbarButton(iItemID, "New", 
                  Drawable::createFromImageData(
                  TImagesFactory::psNew_png, 
                  TImagesFactory::iNew_pngSize),
                  0);
            return pFileNewButton;
        }
        case FileOpen:
        {
                  pFileOpenButton = new ToolbarButton(iItemID, "Open", 
                  Drawable::createFromImageData(
                  TImagesFactory::psOpen_png, 
                  TImagesFactory::iOpen_pngSize),
                  0);
                return pFileOpenButton;
            }
            case ViewOrientation:
            {
                pViewOrientationButton = new ToolbarButton(iItemID, "Orientation", 
                   Drawable::createFromImageData(
                   TImagesFactory::psRotate_png, 
                   TImagesFactory::iRotate_pngSize),
                0);
            return pViewOrientationButton;
          }
          default:
          {
          break;
        }
      }
    
      return 0;
    }
    //-------------------------------------------
    

    В конструкторе класса мы инициализируем переменные-члены типа Image бинарными данными, полученными из созданного ранее пространства имён TImagesFactory.

    В функции ), то для разделителя и распорки берём стандартные — separatorBarId и spacerId, соответственно.

    В функции ).

    В функции createItem мы создаём собственно элементы инструментальной панели (кроме разделителей и распорок, для которых этого делать не нужно), "привязывая" их к индексам, заданным методом getAllToolbarItemIds. В нашем случае элементами инструментальной панели будут исключительно кнопки класса ToolbarButton. Их свойства и методы большей частью совпадают с таковыми других кнопок с изображениями, описанных в лекции 12 .

    Конструктор кнопок инструментальной панели ToolbarButton::ToolbarButton(int itemId, const String labelText, Drawable* normalImage, Drawable* toggledOnImage) принимает следующие параметры:

  • int itemId — уникальный числовой идентификатор (ID);
  • labelText — надпись (как правило не видна, так что можно инициировать этот параметр пустой строкой);
  • normalImage — изображение на кнопке;
  • toggledOnImage — изображение на кнопке, находящейся в фиксированном (on) состоянии. Если параметр принимает значение 0, то будет использовано изображение normalImage вне зависимости от того, была ли включена фиксация кнопки методом getToggleState.
  • В нашем примере мы не включали фиксацию кнопок, поэтому в их конструкторы передаём только одно изображение из числа инициализированных в конструкторе ().

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

    Помимо собственно инструментальной панели в нашем приложении будет присутствовать полоса состояния (см. лекцию 11 ) для отображения подсказок от кнопок, а также ярлык. На нём будут выводиться сообщения о щелчке по той или иной кнопке (реально работать у нас будут только ). Объект созданного нами класса TToolbarFactory добавим в компонент содержимого в качестве закрытого члена.

    #ifndef _TCentralComponent_h_
    #define _TCentralComponent_h_
    //--------------------------------------------
    #include "../JuceLibraryCode/JuceHeader.h"
    // Подключаем наш класс "фабрики" панели инструментов
    #include "TToolbarFactory.h"
    //--------------------------------------------
    class TStatusBar;
    //--------------------------------------------
    // Класс компонента содержимого.
    // Наследует класс слушателя кнопок
    class TCentralComponent  : public Component,
          public ButtonListener
    {
    public:
      TCentralComponent();
      ~TCentralComponent();
    
      void paint(Graphics);
      void resized();
      // Функция, отслеживающая щелчки по кнопке
      void buttonClicked(Button*);
      // Функция, отслеживающая движение мыши
      void mouseMove(const MouseEvent);
    
    private:
      // Ярлык для вывода сообщений
      Label* pInfoLabel;
      // Панель инструментов
      Toolbar* pToolbar;
      TToolbarFactory ToolbarFactory;
      // Полоса состояния
      TStatusBar* pStatusBar;
    
      // Предотвращает создание копии конструктора и оператора =
      TCentralComponent(const TCentralComponent);
      const TCentralComponent operator= (const TCentralComponent);
    };
    //------------------------------------
    #endif
    

    Сам по себе объект класса Toolbar лишь создаёт полосу для добавления элементов, однако может определять стиль их отображения. Для этого используется метод void Toolbar::setStyle(const ToolbarItemStyle newStyle), который в качестве параметра принимает идентификатор перечислимого типа ToolbarItemStyle:

  • iconsOnly — панель инструментов отображает лишь пиктограммы кнопок (по умолчанию);
  • iconsWithText — под каждой кнопкой будет отображаться её надпись (второй параметр конструктора) в стиле KDE;
  • textOnly — вместо кнопок на панели инструментов будут отображаться их ярлыки с надписями.
  • В нашем примере мы не используем этот метод.

    Для создания и последующего отображения элементов инструментальной панели необходимо создать объект класса, унаследованного от ).

    #include "TCentralComponent.h"
    #include "TStatusBar.h"
    //---------------------------------------------
    #define tr(s) String::fromUTF8(s)
    //---------------------------------------------
    TCentralComponent::TCentralComponent() : Component ("Central Component"),
               pInfoLabel(0),
               pToolbar(0)
    {
      // Создаём панель инструментов
      pToolbar = new Toolbar();
      addAndMakeVisible(pToolbar);
      // Панель инструментов - горизонтальная
      pToolbar->setVertical(false);
      // Добавляем на панель кнопки
      pToolbar->addDefaultItems(ToolbarFactory);
      // Добавляем слушатель мыши
      pToolbar->addMouseListener(this, true);
      
      // Добавляем слушатели кнопок
      ToolbarFactory.pFileNewButton->addListener(this);
      ToolbarFactory.pFileQuitButton->addListener(this);
      ToolbarFactory.pFileOpenButton->addListener(this);
      ToolbarFactory.pViewOrientationButton->addListener(this);
      
      pInfoLabel = new Label("Info Label", 
          tr("Нажмите кнопку панели инструментов!"));
      pInfoLabel->setJustificationType(Justification::centred);
      pInfoLabel->setColour(Label::backgroundColourId, Colours::azure);
      addAndMakeVisible(pInfoLabel);
      
      // Создаём панель состояния
      pStatusBar = new TStatusBar();
      pStatusBar->ShowHint(tr("Готов"));
      addAndMakeVisible(pStatusBar);
    
      setSize (400, 200);
    }
    

    Библиотека Juce позволяет создавать инструментальные панели двух видов: вертикальные и горизонтальные (традиционные). Для того, чтобы задать ориентацию панели, необходимо вызвать метод ).

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

    Для того, чтобы панель инструментов, будучи вертикальной, не перекрывала полосу состояния, мы рассчитываем длину первой (). Узнать ориентацию инструментальной панели нам помогает метод bool Toolbar::isVertical() const throw().

    void TCentralComponent::resized()
    {
      if(pToolbar->isVertical())
      {
        pToolbar->setBounds(0, 0, 25, getHeight() - 25);
        pInfoLabel->setBounds(25, proportionOfHeight(0.5000f),  
            proportionOfWidth(1.0000f), 25);
      }
      else
      {
        pToolbar->setBounds(0, 0, getWidth(), 25);
        pInfoLabel->setBounds(0, proportionOfHeight(0.5000f), 
            proportionOfWidth(1.0000f), 25);
      }
      
      pStatusBar->setBounds(0, proportionOfHeight(1.0000f) - 25, 
            proportionOfWidth(1.0000f), 25);
    }
    

    Собственно логика работы программы приведена в листинге 14.6 и понятна без дополнительных комментариев.

    void TCentralComponent::buttonClicked(Button* pButton)
    {
      if(pButton == ToolbarFactory.pFileQuitButton)
      {
        JUCEApplication::quit();
      }
      else if(pButton == ToolbarFactory.pFileNewButton)
      {
        pInfoLabel->setText(tr("Нажата кнопка \"Новый\"."), false);
      }
      else if(pButton == ToolbarFactory.pFileOpenButton)
      {
        pInfoLabel->setText(tr("Нажата кнопка \"Открыть\"."), false);
      }
      else if(pButton == ToolbarFactory.pViewOrientationButton)
      {
        pToolbar->setVertical(!pToolbar->isVertical());
        this->resized();
        pInfoLabel->setText(tr("Нажата кнопка \"Ориентация\"."), false);
      }
    }
    //------------------------------------------------
    void TCentralComponent::mouseMove(const MouseEvent Event)
    {
      // Отработка показа подсказок кнопок панели инструментов при наведении
      // на них мыши
      if(Event.source.getComponentUnderMouse() == ToolbarFactory.pFileQuitButton)
      {
        pStatusBar->ShowHint(tr("Нажмите, чтобы завершить работу программы"));
      }
      else if(Event.source.getComponentUnderMouse() == 
            ToolbarFactory.pFileNewButton)
      {
        pStatusBar->ShowHint(tr("Нажмите эту кнопку"));
      }
      else if(Event.source.getComponentUnderMouse() ==
             ToolbarFactory.pFileOpenButton)
      {
        pStatusBar->ShowHint(tr("Нажмите эту кнопку"));
      }
      else if(Event.source.getComponentUnderMouse() == 
             ToolbarFactory.pViewOrientationButton)
      {
        pStatusBar->ShowHint(
             tr("Нажмите эту кнопку, чтобы установить панель 
               инструментов вертикально / горизонтально"));
      }
      else
      {
        pStatusBar->ShowHint(tr("Готов"));
      }
    }
    

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

    (рис 14.2) Вертикальное расположение инструментальной панели

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

    Для создания панели инструментов приложения нам необходимо описать набор команд и связать его с соответствующими инструментальными кнопками ToolbarButton, которые добавляются на панель объектом класса ToolbarItemFactory. За отрисовку полосы (панели), содержащей эти кнопки в порядке, определяемом ToolbarItemFactory, отвечает объект класса Toolbar.

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

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

    Страницы:

    Цель лекции: Научиться создавать и использовать панели инструментов в своих программах

    Для построения панели инструментов библиотека Juce предоставляет классы Toolbar, ToolbarItemFactory и ToolbarButton.

    Toolbar — компонент, который рисует вертикальную или горизонтальную полосу (панель), содержащую кнопки или иные виджеты в порядке, определяемом ToolbarItcodeFactory.

    ToolbarItemFactory отвечает за создание и добавление на панель инструментов её элементов. Каждый тип добавляемых элементов должен характеризоваться уникальным номером (ID), включая разделители и распорки.

    ToolbarButton — "быстрая" кнопка инструментальной панели, наиболее часто добавляемый на неё виджет. Этот тип кнопок отличается тем, что содержит вместо надписи небольшое изображение (пиктограмму, icon), символизирующее определённую команду меню.

    Класс ToolbarButton является потомком ToolbarItemComponent, с помощью которого можно создавать произвольные виджеты для добавления на панель инструментов.

    Программа, окно которой показано на рисунке 14.1 , демонстрирует применение всех вышеперечисленных классов.

    (рис 14.1) Программа, демонстрирующая работу панели инструментов

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

    Как упоминалось, за создание кнопок панели инструментов отвечает класс ToolbarItemFactory. Он является абстрактным и включает три чистые виртуальные функции:

  • virtual void ToolbarItemFactory::getAllToolbarItemIds(Array<int> ids) — задаёт массив уникальных числовых не равных нулю идентификаторов (ID) для каждого из типов элементов, которые может создавать ToolbarItemFactory;
  • virtual void ToolbarItemFactory::getDefaultItemSet(Array<int> ids) — задаёт собственно сам набор добавляемых на панель инструментов элементов, основываясь на наборе идентификаторов, созданных предыдущей функцией;
  • virtual ToolbarItemComponent* ToolbarItemFactory::createItem(int itemId) — создаёт компонент (например, кнопку), добавляемый на панель инструментов, из числа набора, основываясь на наборе идентификаторов, созданных предыдущей функцией.
  • Объявим собственный класс, , ).

    #ifndef _TTolbarFactory_h_
    #define _TTolbarFactory_h_
    //-----------------------------------------------
    #include "../JuceLibraryCode/JuceHeader.h"
    //------------------------------------------------
    // "Фабрика" для создания кнопок панели инструментов
    class TToolbarFactory : public ToolbarItemFactory
    {
    public:
      TToolbarFactory();
      ~TToolbarFactory();
    
      // Идентификаторы создаваемых кнопок
      enum TToolbarItemID
      {
        FileNew = 1,
        FileOpen = 2,
        FileQuit = 3,
        ViewOrientation = 4
      };
    
      // Задаёт идентификаторы кнопок
      void getAllToolbarItemIds(Array<int>);
      // Задаёт набор кнопок панели инструментов 
      void getDefaultItemSet(Array<int>);
      // Создаёт элемент панели инструментов
      ToolbarItemComponent* createItem(int);
    
      // Кнопка "Выход"
      ToolbarButton* pFileQuitButton;
      // Кнопка "Новый"
      ToolbarButton* pFileNewButton;
      // Кнопка "Открыть"
      ToolbarButton* pFileOpenButton;
      // Кнопка "Ориентация"
      ToolbarButton* pViewOrientationButton;
    
    private:
      // Изображения - пиктограммы кнопок
      Image ImageExit_png;
      Image ImageNew_png;
      Image ImageOpen_png;
      Image ImageSwitch_png;
    };
    //-----------------------------------------
    #endif
    

    В качестве члена класса мы создали перечислимый список TToolbarItemID идентификаторов кнопок (в принципе, его можно объявить и вне класса, например, если вы хотите использовать один набор идентификаторов команд для кнопок панели инструментов и пунктов меню). В качестве открытых членов класса мы объявили указатели на кнопки — элементы панели инструментов, а закрытых — добавляемые на их поверхность изображения (класс Image).

    Рассмотрим реализацию нашего класса . В большей своей части она состоит из реализации вышеупомянутых чистых виртуальных функций getAllToolbarItemIds, getDefaultItemSet и createItem.

    #include "TToolbarFactory.h"
    // Подключаем бинарные ресурсы изображений
    #include "TImagesFactory.h"
    //--------------------------------------
    TToolbarFactory::TToolbarFactory()
    {
      // Загружаем изображения в объекты класса Image из памяти
      ImageExit_png = ImageCache::getFromMemory(TImagesFactory::psExit_png,
                  TImagesFactory::iExit_pngSize);
      ImageNew_png = ImageCache::getFromMemory(TImagesFactory::psNew_png, 
                  TImagesFactory::iNew_pngSize);
      ImageOpen_png = ImageCache::getFromMemory(TImagesFactory::psOpen_png, 
                  TImagesFactory::iOpen_pngSize);
      ImageSwitch_png = ImageCache::getFromMemory(TImagesFactory::psRotate_png, 
                  TImagesFactory::iRotate_pngSize);
    }
    //--------------------------------------
    TToolbarFactory::~TToolbarFactory()
    {
    }
    //----------------------------------------
    void TToolbarFactory::getAllToolbarItemIds(Array<int> iIDs)
    {
      // Задаём список идентификаторов элементов панели инструментов: 
      // кнопок, разделителей (separators) и распорок (spacers)
      iIDs.add(FileNew);
      iIDs.add(FileOpen);
      iIDs.add(FileQuit);
      iIDs.add(ViewOrientation);
      iIDs.add(spacerId);
      iIDs.add(separatorBarId);
    }
    //-------------------------------------------
    void TToolbarFactory::getDefaultItemSet(Array<int> iIDs)
    {
      // Определяем порядок добавления элементов на инструментальную панель
      iIDs.add(FileQuit);
      iIDs.add(separatorBarId);
      iIDs.add(FileNew);
      iIDs.add(FileOpen);
      iIDs.add(separatorBarId);
      iIDs.add(ViewOrientation);
    }
    //----------------------------------------------
    ToolbarItemComponent* TToolbarFactory::createItem(int iItemID)
    {
      switch(iItemID)
      {
        // Создаём кнопки панели инструментов, "привязывая" их 
        // к ранее созданным идентификаторам
        case FileQuit:
        {
            pFileQuitButton = new ToolbarButton(iItemID, "Quit", 
                Drawable::createFromImageData(
                TImagesFactory::psExit_png, 
                TImagesFactory::iExit_pngSize),
              0);
            return pFileQuitButton;
          }
          case FileNew:
          {
          pFileNewButton = new ToolbarButton(iItemID, "New", 
                  Drawable::createFromImageData(
                  TImagesFactory::psNew_png, 
                  TImagesFactory::iNew_pngSize),
                  0);
            return pFileNewButton;
        }
        case FileOpen:
        {
                  pFileOpenButton = new ToolbarButton(iItemID, "Open", 
                  Drawable::createFromImageData(
                  TImagesFactory::psOpen_png, 
                  TImagesFactory::iOpen_pngSize),
                  0);
                return pFileOpenButton;
            }
            case ViewOrientation:
            {
                pViewOrientationButton = new ToolbarButton(iItemID, "Orientation", 
                   Drawable::createFromImageData(
                   TImagesFactory::psRotate_png, 
                   TImagesFactory::iRotate_pngSize),
                0);
            return pViewOrientationButton;
          }
          default:
          {
          break;
        }
      }
    
      return 0;
    }
    //-------------------------------------------
    

    В конструкторе класса мы инициализируем переменные-члены типа Image бинарными данными, полученными из созданного ранее пространства имён TImagesFactory.

    В функции ), то для разделителя и распорки берём стандартные — separatorBarId и spacerId, соответственно.

    В функции ).

    В функции createItem мы создаём собственно элементы инструментальной панели (кроме разделителей и распорок, для которых этого делать не нужно), "привязывая" их к индексам, заданным методом getAllToolbarItemIds. В нашем случае элементами инструментальной панели будут исключительно кнопки класса ToolbarButton. Их свойства и методы большей частью совпадают с таковыми других кнопок с изображениями, описанных в лекции 12 .

    Конструктор кнопок инструментальной панели ToolbarButton::ToolbarButton(int itemId, const String labelText, Drawable* normalImage, Drawable* toggledOnImage) принимает следующие параметры:

  • int itemId — уникальный числовой идентификатор (ID);
  • labelText — надпись (как правило не видна, так что можно инициировать этот параметр пустой строкой);
  • normalImage — изображение на кнопке;
  • toggledOnImage — изображение на кнопке, находящейся в фиксированном (on) состоянии. Если параметр принимает значение 0, то будет использовано изображение normalImage вне зависимости от того, была ли включена фиксация кнопки методом getToggleState.
  • В нашем примере мы не включали фиксацию кнопок, поэтому в их конструкторы передаём только одно изображение из числа инициализированных в конструкторе ().

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

    Помимо собственно инструментальной панели в нашем приложении будет присутствовать полоса состояния (см. лекцию 11 ) для отображения подсказок от кнопок, а также ярлык. На нём будут выводиться сообщения о щелчке по той или иной кнопке (реально работать у нас будут только ). Объект созданного нами класса TToolbarFactory добавим в компонент содержимого в качестве закрытого члена.

    #ifndef _TCentralComponent_h_
    #define _TCentralComponent_h_
    //--------------------------------------------
    #include "../JuceLibraryCode/JuceHeader.h"
    // Подключаем наш класс "фабрики" панели инструментов
    #include "TToolbarFactory.h"
    //--------------------------------------------
    class TStatusBar;
    //--------------------------------------------
    // Класс компонента содержимого.
    // Наследует класс слушателя кнопок
    class TCentralComponent  : public Component,
          public ButtonListener
    {
    public:
      TCentralComponent();
      ~TCentralComponent();
    
      void paint(Graphics);
      void resized();
      // Функция, отслеживающая щелчки по кнопке
      void buttonClicked(Button*);
      // Функция, отслеживающая движение мыши
      void mouseMove(const MouseEvent);
    
    private:
      // Ярлык для вывода сообщений
      Label* pInfoLabel;
      // Панель инструментов
      Toolbar* pToolbar;
      TToolbarFactory ToolbarFactory;
      // Полоса состояния
      TStatusBar* pStatusBar;
    
      // Предотвращает создание копии конструктора и оператора =
      TCentralComponent(const TCentralComponent);
      const TCentralComponent operator= (const TCentralComponent);
    };
    //------------------------------------
    #endif
    

    Сам по себе объект класса Toolbar лишь создаёт полосу для добавления элементов, однако может определять стиль их отображения. Для этого используется метод void Toolbar::setStyle(const ToolbarItemStyle newStyle), который в качестве параметра принимает идентификатор перечислимого типа ToolbarItemStyle:

  • iconsOnly — панель инструментов отображает лишь пиктограммы кнопок (по умолчанию);
  • iconsWithText — под каждой кнопкой будет отображаться её надпись (второй параметр конструктора) в стиле KDE;
  • textOnly — вместо кнопок на панели инструментов будут отображаться их ярлыки с надписями.
  • В нашем примере мы не используем этот метод.

    Для создания и последующего отображения элементов инструментальной панели необходимо создать объект класса, унаследованного от ).

    #include "TCentralComponent.h"
    #include "TStatusBar.h"
    //---------------------------------------------
    #define tr(s) String::fromUTF8(s)
    //---------------------------------------------
    TCentralComponent::TCentralComponent() : Component ("Central Component"),
               pInfoLabel(0),
               pToolbar(0)
    {
      // Создаём панель инструментов
      pToolbar = new Toolbar();
      addAndMakeVisible(pToolbar);
      // Панель инструментов - горизонтальная
      pToolbar->setVertical(false);
      // Добавляем на панель кнопки
      pToolbar->addDefaultItems(ToolbarFactory);
      // Добавляем слушатель мыши
      pToolbar->addMouseListener(this, true);
      
      // Добавляем слушатели кнопок
      ToolbarFactory.pFileNewButton->addListener(this);
      ToolbarFactory.pFileQuitButton->addListener(this);
      ToolbarFactory.pFileOpenButton->addListener(this);
      ToolbarFactory.pViewOrientationButton->addListener(this);
      
      pInfoLabel = new Label("Info Label", 
          tr("Нажмите кнопку панели инструментов!"));
      pInfoLabel->setJustificationType(Justification::centred);
      pInfoLabel->setColour(Label::backgroundColourId, Colours::azure);
      addAndMakeVisible(pInfoLabel);
      
      // Создаём панель состояния
      pStatusBar = new TStatusBar();
      pStatusBar->ShowHint(tr("Готов"));
      addAndMakeVisible(pStatusBar);
    
      setSize (400, 200);
    }
    

    Библиотека Juce позволяет создавать инструментальные панели двух видов: вертикальные и горизонтальные (традиционные). Для того, чтобы задать ориентацию панели, необходимо вызвать метод ).

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

    Для того, чтобы панель инструментов, будучи вертикальной, не перекрывала полосу состояния, мы рассчитываем длину первой (). Узнать ориентацию инструментальной панели нам помогает метод bool Toolbar::isVertical() const throw().

    void TCentralComponent::resized()
    {
      if(pToolbar->isVertical())
      {
        pToolbar->setBounds(0, 0, 25, getHeight() - 25);
        pInfoLabel->setBounds(25, proportionOfHeight(0.5000f),  
            proportionOfWidth(1.0000f), 25);
      }
      else
      {
        pToolbar->setBounds(0, 0, getWidth(), 25);
        pInfoLabel->setBounds(0, proportionOfHeight(0.5000f), 
            proportionOfWidth(1.0000f), 25);
      }
      
      pStatusBar->setBounds(0, proportionOfHeight(1.0000f) - 25, 
            proportionOfWidth(1.0000f), 25);
    }
    

    Собственно логика работы программы приведена в листинге 14.6 и понятна без дополнительных комментариев.

    void TCentralComponent::buttonClicked(Button* pButton)
    {
      if(pButton == ToolbarFactory.pFileQuitButton)
      {
        JUCEApplication::quit();
      }
      else if(pButton == ToolbarFactory.pFileNewButton)
      {
        pInfoLabel->setText(tr("Нажата кнопка \"Новый\"."), false);
      }
      else if(pButton == ToolbarFactory.pFileOpenButton)
      {
        pInfoLabel->setText(tr("Нажата кнопка \"Открыть\"."), false);
      }
      else if(pButton == ToolbarFactory.pViewOrientationButton)
      {
        pToolbar->setVertical(!pToolbar->isVertical());
        this->resized();
        pInfoLabel->setText(tr("Нажата кнопка \"Ориентация\"."), false);
      }
    }
    //------------------------------------------------
    void TCentralComponent::mouseMove(const MouseEvent Event)
    {
      // Отработка показа подсказок кнопок панели инструментов при наведении
      // на них мыши
      if(Event.source.getComponentUnderMouse() == ToolbarFactory.pFileQuitButton)
      {
        pStatusBar->ShowHint(tr("Нажмите, чтобы завершить работу программы"));
      }
      else if(Event.source.getComponentUnderMouse() == 
            ToolbarFactory.pFileNewButton)
      {
        pStatusBar->ShowHint(tr("Нажмите эту кнопку"));
      }
      else if(Event.source.getComponentUnderMouse() ==
             ToolbarFactory.pFileOpenButton)
      {
        pStatusBar->ShowHint(tr("Нажмите эту кнопку"));
      }
      else if(Event.source.getComponentUnderMouse() == 
             ToolbarFactory.pViewOrientationButton)
      {
        pStatusBar->ShowHint(
             tr("Нажмите эту кнопку, чтобы установить панель 
               инструментов вертикально / горизонтально"));
      }
      else
      {
        pStatusBar->ShowHint(tr("Готов"));
      }
    }
    

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

    (рис 14.2) Вертикальное расположение инструментальной панели

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

    Для создания панели инструментов приложения нам необходимо описать набор команд и связать его с соответствующими инструментальными кнопками ToolbarButton, которые добавляются на панель объектом класса ToolbarItemFactory. За отрисовку полосы (панели), содержащей эти кнопки в порядке, определяемом ToolbarItemFactory, отвечает объект класса Toolbar.

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

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

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