Элементы управления. Кнопки
Обратите внимание, что метод 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).
![Внешний вид кнопки со стрелкой (параметр конструктора arrowDirection принимает значение 0.75; arrowColour — Colours::blue)](/EDI/16_08_14_2/1408137470-25747/tutorial/1113/objects/12/files/12_02.jpg)
Рис. 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).
![Изображения для кнопки DrawableButton, подготовленные в GIMP и cохраненные в виде файлов *.png](/EDI/16_08_14_2/1408137470-25747/tutorial/1113/objects/12/files/12_03.jpg)
Рис. 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)