| Россия |
Элементы управления. Кнопки
Обратите внимание, что метод changeWidthToFitText должен вызываться дважды: в обработчике щелчка по кнопке buttonClicked, и в функции resized; в противном случае при каждом изменении размеров окна, например, растягивании, кнопка будет возвращаться к начальной форме, заданной параметрами метода setBounds.
Зачастую в надписи на кнопке один из символов подчеркнут. Это означает, что пользователь может нажать комбинацию клавиш <ALT>+<S>, где <S> - это подчеркнутый символ, и это будет эквивалентно щелчку по кнопке. Добиться этого можно с помощью метода void Button::addShortcut(const KeyPress& key), где key — код "горячей" клавиши с или без модификатора (<CTRL>, <ALT>, <SHIFT> и т.п.). Например, если нам нужно, чтобы обработчик щелчка по кнопке pCloseButton срабатывал при нажатии клавиш <ALT>+<Q>, необходимо вызвать метод addShortcut следующим образом:
pCloseButton->addShortcut(KeyPress('q', ModifierKeys::altModifier, 0))
В этом примере мы создали новый объект класса KeyPress, отслеживающего нажатие клавиш клавиатуры, в конструктор которого в качестве параметров передали код "горячей" клавиши ('q') и ее модификатора. Третий параметр — печатаемый символ (в нашем случае равен нулю, т.к. вызывающий виджет не является полем ввода).
В свою очередь, созданный объект класса KeyPress передается в метод addShortcut в качестве параметра. Ниже приведены некоторые идентификаторы перечислимого типа enum ModifierKeys:
- shiftModifier — флаг нажатия на клавишу <SHIFT>;
- ctrlModifier — флаг нажатия на клавишу <CTRL>;
- altModifier — флаг нажатия на клавишу <ALT>.
Помимо этого, ModifierKeys содержит модификаторы, связанные с различными манипуляциями кнопками мыши.
Разумеется, можно зарегистрировать для кнопки "горячую" клавишу безо всякого модификатора. Например, если в качестве параметра в метод addShortcut кнопки "Отменить" передать в качестве параметра KeyPress::escapeKey, то нажатие пользователем клавиши <ESC> будет эквивалентно щелчку по данной кнопке. Это целесообразно делать в различных диалоговых окнах, чтобы пользователь мог их закрывать без использования мыши.
Для того, чтобы отключить все "горячие" клавиши, зарегистрированные для данной кнопки, используют метод void Button::clearShortcuts().
Основное событие любой кнопки — это щелчок по ней. При этом вызывается виртуальный защищенный метод virtual void Button::clicked(). Отслеживает событие щелчка по кнопке ее слушатель, Button::Listener. Именно в его методе virtual void Button::Listener::buttonClicked(Button* button) записываются все операторы, которые должны выполняться при щелчке пользователя по кнопке (см., например, пример 12.1). Метод является чистой виртуальной (pure virtual) функцией и должен быть обязательно переопределен в производном классе.
Практически все, сказанное выше, относится и к другим кнопкам.
ArrowButton — это кнопка со стрелкой в виде треугольника. Поскольку внешний вид (цвет, направление) стрелки задаются один раз при создании кнопки, последняя выполняет исключительно декоративные функции ( рис. 12.2).

Рис. 12.2. Внешний вид кнопки со стрелкой (параметр конструктора arrowDirection принимает значение 0.75; arrowColour — Colours::blue)
Конструктор кнопки ArrowButton::ArrowButton(const String& buttonName, float arrowDirection, const Colour& arrowColour) принимает три параметра:
- buttonName — имя кнопки;
- arrowDirection — направление кнопки, где при принимаемом значении 0.0 стрелка направлена вправо, 0.25 — вниз, 0.5 — влево, а 0.75 — вверх;
- arrowColour — цвет стрелки.
DrawableButton — это кнопка, которая отображает один или несколько объектов класса, производного от Drawable. Drawable — это базовый класс для объектов, которые могут рисовать сами на себе графические примитивы (полигоны) или изображения (например, загруженные из файла). Поскольку Drawable является абстрактным классом, включающим ряд чистых виртуальных функций-членов, на практике используют производный от него класс, DrawableImage объект которого представляет собой битовое изображение (bitmap).
При необходимости возможно использование других производных от Drawable классов, например, DrawableShape или DrawableText.
Конструктор DrawableButton::DrawableButton(const String& buttonName, ButtonStyle buttonStyle) создает "пустую", т.е. не содержащую никаких изображений кнопку.
В качестве параметров конструктор принимает строку — имя кнопки (buttonName) и ее стиль, идентификатор перечислимого типа enum DrawableButton::ButtonStyle.
Стили у DrawableButton могут быть следующими:
- ImageFitted — кнопка отображает объекты Drawable, изменяя их размеры таким образом, чтобы изображения помещались внутри кнопки;
- ImageRaw — кнопка показывает изображения с их исходными размерами;
- ImageAboveTextLabel — кнопка отображает надпись, заданную методом setButtonText, и объект Drawable с размерами, измененными таким образом, чтобы изображение поместилось над надписью рис. 12.4
- ImageOnButtonBackground — рисуется стандартная для Juce кнопка с наложенным поверх изображением Drawable.
Следует помнить, что программист должен сам позаботиться о соответствии размеров изображения, отображаемого DrawableImage и размеров кнопки DrawableButton.
Рассмотрим использование DrawableButton на простейшем примере, когда кнопка отображает заранее созданные с помощью графического редактора GIMP изображения, загружаемые из файлов в формате *.png, находящихся в каталоге нашей программы ( рис. 12.3).

Рис. 12.3. Изображения для кнопки DrawableButton, подготовленные в GIMP и cохраненные в виде файлов *.png
В качестве основы для нашей программы используем код из вышеприведенного примера, заменив класс у pCloseButton с TextButton на DrawableButton пример 12.2 .
#include "TCentralComponent.h"
//---------------------------------------------------------------------
#define tr(s) String::fromUTF8(s)
//---------------------------------------------------------------------
TCentralComponent::TCentralComponent() : Component ("Central Component"),
pHelloLabel(0),
pCloseButton(0)
{
pHelloLabel = new Label("Hello Label", tr("Привет, мир!"));
addAndMakeVisible(pHelloLabel);
pHelloLabel->setFont(Font(38.0000f, Font::bold));
pHelloLabel->setJustificationType(Justification::centred);
pHelloLabel->setEditable(false, false, false);
pHelloLabel->setColour(Label::textColourId, Colours::blue);
pHelloLabel->setColour(TextEditor::textColourId, Colours::black);
pHelloLabel->setColour(TextEditor::backgroundColourId, Colours::azure);
// Получаем рабочий каталог программы и сохраняем путь к нему
// в виде строки
String sPath = File::getCurrentWorkingDirectory().getFullPathName();
// Полное имя файла изображения ненажатой кнопки
String sUp;
// Полное имя файла изображения нажатой кнопки
String sDown;
// Получаем полные имена файлов изображений для Windows и Linux
#if JUCE_WINDOWS
sUp = sPath + "\\gimpbutton-up.png";
sDown = sPath + "\\gimpbutton-down.png";
#elif JUCE_LINUX
sUp = sPath + "/gimpbutton-up.png";
sDown = sPath + "/gimpbutton-down.png";
#endif
// Изображение для ненажатой кнопки
DrawableImage UpImage;
// Изображение для нажатой кнопки
DrawableImage DownImage;
// Загружаем изображение в DrawableImage из соответствующего файла
UpImage.setImage(ImageCache::getFromFile(File(sUp)));
DownImage.setImage(ImageCache::getFromFile(File(sDown)));
// Создаем пустую DrawableButton
pCloseButton = new DrawableButton("CloseButton",
DrawableButton::ImageAboveTextLabel);
// Устанавливаем изображения для различных состояний кнопки
pCloseButton->setImages(& UpImage, & UpImage, & DownImage);
addAndMakeVisible(pCloseButton);
pCloseButton->setButtonText(tr("Закрыть"));
pCloseButton->addListener(this);
setSize (400, 200);
}
//---------------------------------------------------------------------
TCentralComponent::~TCentralComponent()
{
deleteAllChildren();
}
//---------------------------------------------------------------------
void TCentralComponent::paint(Graphics& Canvas)
{
Canvas.fillAll(Colours::azure);
}
//---------------------------------------------------------------------
void TCentralComponent::resized()
{
pHelloLabel->setBounds(0, 0, proportionOfWidth(1.0000f), proportionOfHeight(0.9000f));
pCloseButton->setBounds(getWidth() - 10 - 204, getHeight() - 60, 204, 53);
}
//---------------------------------------------------------------------
void TCentralComponent::buttonClicked(Button* pButton)
{
if (pButton == pCloseButton)
{
JUCEApplication::quit();
}
}
//---------------------------------------------------------------------
Листинг
12.2.
Реализация класса компонента содержимого TCentralComponent (файл TCentralComponent.cpp)