Цель лекции: Научиться создавать и использовать диалоговые окна различного назначения
В приложениях с графическим интерфейсом часто приходится выполнять действия, связанные либо с показом пользователю какой-либо информации, либо с выбором последним каких-либо параметров (выбор файлов и папок, цветов палитры и т.п.), что реализуется с помощью диалоговых окон. В законченном приложении их желательно проектировать самому, обеспечивая единство стиля всех окон программы. Именно поэтому в Juce подавляющее большинство компонентов, реализующих стандартные диалоги, представлено не законченными окнами, а их заготовками. Комбинацией подобных заготовок создаются компоненты, которые показываются пользователю с помощью объекта специального класса — DialogWindow.
Лишь простые диалоги, дающие пользователю какие-то указания (информационные окна, предупреждение об ошибках и т.п.) или позволяющие задать ему несложный вопрос, на который возможен стандартный ответ, вроде "да", "нет", "отменить", "прервать", реализуются в виде законченных окон с помощью класса AlertWindow, который мы неоднократно использовали в примерах предыдущих глав.
В данной главе на простых примерах мы рассмотрим как использование диалоговых окон, созданных с помощью AlertWindow, так и с помощью классов-заготовок.
Простейшим диалоговым окном является окно сообщения с закрывающей кнопкой (рисунок 17.1 ). Как уже упоминалось, оно создаётся вызовом метода static void JUCE_CALLTYPE AlertWindow::showMessageBox(AlertIconType iconType, const String title, const String message, const String buttonText = String::empty, Component* associatedComponent = 0), где iconType — тип отображаемой пиктограммы, title — заголовок диалога, message — его сообщение, buttonText — надпись, отображаемая на закрывающей кнопке, а associatedComponent — указатель на компонент, с которым будет ассоциировано диалоговое окно. Если указатель равен нулю, то окно будет позиционировано в центре вызывающего компонента.
Вид пиктограммы, отображаемой на диалоге, задаётся enum AlertWindow::AlertIconType, идентификатором которого являются:
NoIcon — диалог не содержит пиктограммы;QuestionIcon — пиктограмма представлена знаком вопроса;WarningIcon — пиктограмма представлена восклицательным знаком;InfoIcon — пиктограмма представлена буквой "i". Пример использования метода showMessageBox приведён в листинге 9.4.
Для отображения диалога с двумя кнопками (например, "да" и "нет", "принять", "отменить" и т.п.) используется метод static bool JUCE_CALLTYPE AlertWindow::showOkCancelBox(AlertIconType iconType, const String title, const String message, const String button1Text = String::empty, const String button2Text = String::empty, Component* associatedComponent = 0). Параметры метода аналогичны вышеописанным; button1Text и button2Text — как понятно, это надписи, отображаемые первой и второй кнопками, соответственно.
Метод возвращает истину в случае, если была нажата первая кнопка, и ложь — если вторая.
Рассмотрим использование этого метода на примере шуточной программы "Примета", знакомой многим из школьного курса информатики.
Окно программы будет включать ярлык для вывода информирующих сообщений и кнопку, нажатие на которую будет вызывать диалоговое окно (рис 17.1 ).
(рис 17.1) Программа "Примета"
Реализация компонента содержимого программы приведена в листинге 17.1 ; логика её работы определена обработчиком нажатия на кнопку buttonClicked.
#include "TCentralComponent.h"
//--------------------------------------------
#define tr(s) String::fromUTF8(s)
//--------------------------------------------
TCentralComponent::TCentralComponent() : Component("Central Component"),
pInfoLabel(0),
pQuestionButton(0)
{
// Ярлык для вывода информационного сообщения
pInfoLabel = new Label(L"Info Label",
tr("Нажмите на кнопку, чтобы начать..."));
pInfoLabel->setFont(Font(15.0000f, Font::bold));
pInfoLabel->setJustificationType(Justification::centred);
pInfoLabel->setEditable(false, false, false);
pInfoLabel->setColour(Label::textColourId, Colours::black);
pInfoLabel->setColour(Label::backgroundColourId, Colours::azure);
pInfoLabel->setColour(Label::outlineColourId, Colours::black);
addAndMakeVisible(pInfoLabel);
// Кнопка вызова диалогового окна
pQuestionButton = new TextButton(L"Question Button");
pQuestionButton->setButtonText(tr("Задать вопрос..."));
pQuestionButton->addListener(this);
addAndMakeVisible(pQuestionButton);
setSize (400, 150);
}
//------------------------------------------
TCentralComponent::~TCentralComponent()
{
// Удаляем дочерние виджеты
// и обнуляем их указатели
deleteAllChildren();
}
//------------------------------------------
void TCentralComponent::paint(Graphics Canvas)
{
Canvas.fillAll(Colours::azure);
}
//-----------------------------------------
void TCentralComponent::resized()
{
pInfoLabel->setBounds(10, 10, getWidth() - 20, 25);
pQuestionButton->setBounds(proportionOfWidth(0.5000f) - ((150) / 2),
proportionOfHeight(0.5000f) - ((25) / 2),
150, 25);
}
//------------------------------------------
void TCentralComponent::buttonClicked(Button* pButton)
{
if(pButton == pQuestionButton)
{
// Сообщение пользователю
String sMessage = String::empty;
// Задаём вопрос - вызываем диалоговое окно
bool bAnswer = AlertWindow::showOkCancelBox(AlertWindow::QuestionIcon,
tr("Примета"),
tr("Верите ли Вы в приметы?"),
tr("Да"),
tr("Нет"), 0);
// Если да...
if(bAnswer)
{
// формируем сообщение, которое будет выводиться красным цветом
sMessage = tr("Верить в приметы - плохая примета!");
pInfoLabel->setColour(Label::textColourId, Colours::red);
}
// Если нет...
else
{
// формируем сообщение, которое будет выводиться синим цветом
sMessage = tr("Поздравляю, Вы - очень разумный человек!");
pInfoLabel->setColour(Label::textColourId, Colours::blue);
}
// Показываем сообщение
pInfoLabel->setText(sMessage, false);
}
}
//-----------------------------------------------------
Внешний вид программы после нажатия на кнопку приведён на рисунке 17.2.
(рис 17.2) Программа "Примета" (показано диалоговое окно с двумя кнопками)
Для отображения диалогового окна с тремя кнопками (например, "да", "нет", "отменить") используется метод static int JUCE_CALLTYPE AlertWindow::showYesNoCancelBox(AlertIconType iconType, const String title, const String message, const String button1Text = String::empty, const String button2Text = String::empty, const String button3Text = String::empty, Component* associatedComponent = 0). Параметры button1Text, button2Text и button3Text — это надписи, отображаемые первой, второй и третьей кнопками, соответственно.
Метод возвращает следующие значения:
0 — если была нажата третья кнопка (обычно используется как кнопка "Отменить");1— если была нажата первая кнопка (обычно используется как кнопка "Да");2 — если была нажата вторая кнопка (обычно используется как кнопка "Нет").Например, следующий код
int iAnswer = AlertWindow::showYesNoCancelBox(AlertWindow::QuestionIcon,
tr("Выбор"),
tr("Внести запись в базу данных?"),
tr("Да"),
tr("Нет"),
tr("Отменить"), 0);
покажет диалог с вышеперечисленными кнопками (рисунок 17.3 ).
(рис 17.3) Диалоговое окно с тремя кнопками
Диалоговые окна для работы с файлами (открытие, сохранение) и директориями, пожалуй, используются чаще всего в современных приложениях. Библиотека Juce включает несколько компонентов для выбора файлов и каталогов; рассмотрим те из них, которые используются в качестве заготовок для создания диалоговых окон.
).
Для отображения виджета FilenameComponent мы используем "обёртку" - объект класса DialogWindow.
Рассмотрим использование компонента на примере программы, в которой пользователь с помощью диалогового окна выбирает тот или иной файл, который сохраняется в переменной ).
(рис 17.4) Программа, демонстрирующая работу FilenameComponent
Рассмотрим реализацию компонента содержимого нашего примера ().
#include "TCentralComponent.h"
//------------------------------------------
#define tr(s) String::fromUTF8(s)
//------------------------------------------
TCentralComponent::TCentralComponent() : Component("Central Component"),
pNameLabel(0),
pChooseButton(0)
{
// Ярлык для показа имени открытого файла
pNameLabel = new Label(L"Name Label", tr("Выберите файл..."));
pNameLabel->setFont(Font(15.0000f, Font::bold));
pNameLabel->setJustificationType(Justification::centred);
pNameLabel->setEditable(false, false, false);
pNameLabel->setColour(Label::textColourId, Colours::black);
pNameLabel->setColour(Label::backgroundColourId, Colours::azure);
pNameLabel->setColour(Label::outlineColourId, Colours::black);
addAndMakeVisible(pNameLabel);
// Кнопка для вызова диалога открытия файла
pChooseButton = new TextButton(L"Choose Button");
pChooseButton->setButtonText(tr("Выбрать..."));
pChooseButton->addListener(this);
addAndMakeVisible(pChooseButton);
setSize (400, 150);
}
//-----------------------------------------------
TCentralComponent::~TCentralComponent()
{
// Удаляем дочерние виджеты
// и обнуляем их указатели
deleteAllChildren();
}
//------------------------------------------------
void TCentralComponent::paint(Graphics Canvas)
{
Canvas.fillAll(Colours::azure);
}
//------------------------------------------------
void TCentralComponent::resized()
{
pNameLabel->setBounds(10, 10, getWidth() - 20, 25);
pChooseButton->setBounds(proportionOfWidth(0.5000f) - ((150) / 2),
proportionOfHeight(0.5000f) - ((25) / 2),
150, 25);
}
//-------------------------------------------------
void TCentralComponent::buttonClicked(Button* pButton)
{
if(pButton == pChooseButton)
{
// Создаём компонент для выбора файла
FilenameComponent* pFileNameDialog = new FilenameComponent(
String::empty,
ObtainedFile,
true,
false,
false,
String::empty,
String::empty,
tr("Выберите файл...")
);
// Задаём его размер (иначе его не будет видно)
pFileNameDialog->setSize(250, 25);
// Создаём "обёртку" для показа диалога...
DialogWindow::showModalDialog(tr("Выбор файла"),
pFileNameDialog,
NULL,
Colours::azure,
true,
false,
false);
// Когда файл открыт...
ObtainedFile = pFileNameDialog->getCurrentFile();
// проверяем, существует ли он
if(!(ObtainedFile == File::nonexistent))
{
// Выводим на ярлык название файла
pNameLabel->setText(ObtainedFile.getFileName(), false);
}
else
{
pNameLabel->setText(tr("Файл не выбран!"), false);
}
if(pFileNameDialog) delete pFileNameDialog;
}
}
//--------------------------------------------------------------
Как и в предыдущем примере, логика работы программы реализована в методе обработки щелчка по кнопке buttonClicked.
Вначале мы создаём собственно виджет класса FilenameComponent, конструктор которого принимает следующие параметры:
const String name — название компонента;bool canEditFilename — флаг, может ли пользователь вручную редактировать имя файла, отображаемое в выпадающем списке; в том случае, если параметр принимает значение false, изменить имя файла можно, лишь выбрав другой после нажатия кнопки обзора (кнопка с тремя точками);bool isDirectory — если параметр принимает значение true, то выбираются не файлы, а директории (папки);bool isForSaving — если параметр принимает значение true, то пользователь может выбирать несуществующие файлы, вводя их имена вручную, т.к. предполагается, что файлы выбираются для сохранения. Понятно, что для правильной работы диалога в этом случае параметр canEditFilename также должен принимать значение true;const String fileBrowserWildcard — строка-фильтр для отображения файлов по расширениям их имён, например "*.jpg;*.png". В качестве параметра может быть передана и пустая строка; в этом случае будут показаны все файлы;const String enforcedSuffix — если значение параметра — не пустая строка, то она будет автоматически добавляться ко всем именам введённых пользователем или открытых файлов;const String textWhenNothingSelected — в том случае, если в качестве параметра currentFile был передан пустой файл, то в выпадающем списке будет отображаться текст textWhenNothingSelected до тех пор, пока пользователь не выберет какой-либо файл.При нажатии на кнопку обзора вызывается диалог выбора файла, стандартный для целевой операционной системы; в случае Linux вызывается соответствующий диалог Juce, поскольку данная операционная система не имеет стандартной (встроенной) графической среды, а выбор той или иной — KDE, Gnome, Xfce и т.п. — определяется исключительно предпочтениями пользователя.
Как уже упоминалось, для отображения виджета FilenameComponent мы используем метод static int DialogWindow::showModalDialog(const String dialogTitle, Component* contentComponent, Component* componentToCentreAround, const , в который передаём указатель на этот компонент. Метод принимает следующие параметры:
const String dialogTitle — название диалога, которое будет отображаться в строке его заголовка; в нашем примере это "Выбор файла" (см. рисунок 17.4 );Component* componentToCentreAround — если указатель не равен нулю, то он указывает на компонент, который будут отображаться перед нашим диалогом;const Colour backgroundColour — цвет фона диалогового окна;bool escapeKeyTriggersCloseButton — если параметр принимает значение true, то нажатие пользователем клавиши <ESC> клавиатуры закрывает диалоговое окно;bool shouldBeResizable — флаг того, может ли пользователь изменять размеры окна потягиванием мыши;bool useBottomRightCornerResizer — флаг того, следует ли отображать виджет-ресайзер в правом нижнем углу окна.После того, как пользователь выбрал файл в диалоге, собственно его открытие осуществляется методом ), после чего мы производим проверку, не является ли файл пустым, т.е. отсутствующим на жёстком диске. Если валидность файла подтверждена, мы выводим его название без пути, получаемое с помощью метода ).
(рис 17.5) Программа, демонстрирующая работу FilenameComponent (файл открыт, его имя добавлено на ярлык программы)
Кроме того, в библиотеке Juce имеется ещё один комопнент для выбора пользователем файлов, FileChooserDialogBox. Его работу мы рассмотрим в следующем разделе, посвящённом предварительному просмотру открываемых изображений. ImagePreviewComponent, FileBrowserComponent и FileChooserDialogBox
Во время выбора пользователем тех или иных файлов зачастую возникает необходимость предварительного просмотра информации об их свойствах. Особенно часто это требуется при выборе изображений; показ уменьшенной копии графического файла, его миниатюры, значительно облегчает поиск требуемого.
Для реализации предварительного просмотра сведений об открываемом файле в библиотеке Juce имеется класс FilePreviewComponent, а для просмотра информации о графическом файле, включая его миниатюру — ImagePreviewComponent, который наследует классу первого компонента. Объект класса ImagePreviewComponent может быть использован в любых создаваемых компонентах, однако обычно указатель на него передают в качестве параметра в конструктор класса FileBrowserComponent, предназначенного для обозрения и выбора пользователем файлов для открытия и сохранения. Как и в предыдущем примере, для отображения объекта класса FileBrowserComponent необходима "оболочка". В её качестве выступает объект третьего класса — FileChooserDialogBox.
Рассмотрим использование этих трёх классов на простом примере, за основу которого мы возьмём предыдущий (см. , рис 17.5 ), однако при нажатии на кнопку "Выбрать..." будет отображаться диалоговое окно с возможностью предварительного просмотра выбираемого графического файла (рис 17.6 ).
(рис 17.6) Диалоговое окно для открытия графического файла с возможностью предварительного просмотра его миниатюры
Как и в предыдущем примере, логика работы программы реализована в обработчике события нажатия на кнопку ().
void TCentralComponent::buttonClicked(Button* pButton)
{
if(pButton == pChooseButton)
{
// Задаём в качестве стартовой директории для поиска файла
// папку "Документы" текущего пользователя
File InitialFile;
InitialFile =
InitialFile.getSpecialLocation(File::userDocumentsDirectory);
// В качестве фильтра поиска файлов задаём изображения PNG и JPG
WildcardFileFilter ImageFileFilter("*.png;*.jpg", String::empty,
tr("Файлы изображений"));
// Создаём компонент для предварительного просмотра
// открываемых файлов
ImagePreviewComponent ImageViewWidget;
// Компонент для отображения списка файлов
FileBrowserComponent FileBrowser(FileBrowserComponent::openMode |
FileBrowserComponent::canSelectFiles,
InitialFile, ImageFileFilter,
ImageViewWidget);
// Диалог для отображения FileBrowser
FileChooserDialogBox OpenFileDialog(
tr("Открыть изображение"),
tr("Выберите файл изображения, который вы хотите открыть..."),
FileBrowser, false, Colours::azure);
OpenFileDialog.setSize(600, 400);
// Если пользователь выбрал файл...
if(OpenFileDialog.show())
{
// открываем его
InitialFile = FileBrowser.getSelectedFile(0);
}
pNameLabel->setText(InitialFile.getFileName(), false);
}
}
Обзор файлов, имеющихся в той или иной папке, обеспечивает объект класса FileBrowserComponent. Его конструктор принимает следующие параметры:
int flags — флаги, описывающие поведение компонента;const File initialFileOrDirectory — начальный файл или директория, которые будут выбраны при первом открытии компонента. Если параметр принимает значение File::nonexistent, т.е. несуществующий файл, то будет открыта директория, установленная по умолчанию (в Linux это обычно домашняя папка пользователя, в Windows — папка документов);const FileFilter* fileFilter — фильтр отображения тех или иных типов файлов; в том случае, если в качестве параметра конструктор FileBrowserComponent принимает нулевой указатель, будут отображаться все файлы;FilePreviewComponent* previewComp — компонент предварительного просмотра свойств открываемых файлов. Может быть равен нулю; в этом случае файлы будут открываться без предварительного просмотра.FileBrowserComponent являются идентификаторы enum FileBrowserComponent::FileChooserFlags:openMode — обозначает, что компонент позволяет пользователю выбирать существующие файлы для их последующего открытия;saveMode — обозначает, что компонент позволяет пользователю указывать имя файла, который будет использован для сохранения в нём чего-либо;canSelectFiles — обозначает, что пользователь может выбирать файлы;canSelectDirectories — обозначает, что пользователь может выбирать директории;canSelectMultipleItems — обозначает, что пользователь может одновременно выбирать несколько элементов (папок или директорий);useTreeView — обозначает, что вместо простого списка файлов в файловом браузере будет отображаться древовидный;filenameBoxIsReadOnly — обозначает, что пользователь сможет выбирать имя того или иного файла, но не сможет вводить его вручную.В нашем примере в качестве стартовой директории мы задали папку "Документы" текущего пользователя, установили ранее созданный виджет ).
Интерфейс для принятия решения, какие именно файлы являются подходящими для выбора пользователем, реализуют классы FileFilter и WildcardFileFilter, являющийся потомком первого.
Конструктор класса FileFilter в качестве единственного параметра принимает строку — объект класса String — описывающую подходящий фильтр, например "*.jpg".
Конструктор класса WildcardFileFilter, обеспечивающего шаблоны групповых символов для файлового браузера, является более сложным и принимает три параметра:
const String fileWildcardPatterns;const String directoryWildcardPatterns;const String description.В отличие от ).
Как упоминалось, отображает файловый браузер FileBrowserComponent и управляет им класс FileChooserDialogBox. Его конструктор принимает следующие параметры:
const String title — заголовок диалогового окна;const String instructions — FileBrowserComponent; browserComponent — файловый браузер, собственно и отвечающий за выбор пользователем файлов и директорий;bool warnAboutOverwritingExistingFiles — если параметр принимает значение true, пользователь будет получать предупреждение при попытке выбора для сохранения уже существующих файлов;const Colour backgroundColour — фоновый цвет диалога.После показа диалога собственно выбор файла осуществляет метод const File FileBrowserComponent::getSelectedFile(int index) const throw(), который возвращает файл с номером index из числа выбранных пользователем.
Для создания диалога выбора цвета в библиотеке Juce используется класс ), за отображение объекта которого отвечает, как и в предыдущих примерах, класс DialogWindow.
(рис 17.7) Компонент ColourSelector
Компонент ColourSelector позволяет пользователю выбрать мышью цвет из той или иной палитры, либо ввести значения красной, зелёной и синей составляющей цвета (RGB) и прозрачности (альфа-канал) в соответствующие поля ползунков.
Внешний вид компонента можно изменять, передавая в качестве параметров конструктора его класса идентификаторы enum ColourSelector::ColourSelectorOptions:
showAlphaChannel — флаг того, что будет меняться не только RGB, но и альфа-канал цвета;showSliders — флаг отображения в диалоге ползунков, позволяющих пользователю вручную вводить значения RGB и альфа-канала;showColourspace — флаг того, будет ли отображаться шкала выбора оттенка, насыщенности и яркости цвета (HSV).По умолчанию конструктор компонента принимает следующие параметры: ).
По умолчанию виджет ColourSelector создаётся с предустановленным значением текущего цвета FFFFFFFF, что соответствует белому цвету. Но это значение можно поменять, воспользовавшись методом void ColourSelector::setCurrentColour(const .
Напротив, получить текущий цвет можно с помощью метода const .
Рассмотрим использование компонента на простом примере. Внешний вид программы и её код с небольшими изменениями заимствуем из предыдущего примера (, рис 17.2" type="example"/>, (рис 17.8) Приложение, демонстрирующее работу диалога выбора цвета
Ярлык программы окрашивается в цвет, выбираемый пользователем в виджете ).
void TCentralComponent::buttonClicked(Button* pButton)
{
if(pButton == pChooseButton)
{
// Создаём виджет выбора цвета
ColourSelector* pColourDialog = new ColourSelector();
// и устанавливаем его размер
pColourDialog->setSize(600, 400);
// Показываем диалог с созданным виджетом
DialogWindow::showModalDialog(tr("Выбор цвета"),
pColourDialog,
NULL,
Colours::azure,
true,
false,
false);
// Сохраняем текущий цвет виджета в переменной
// после закрытия диалога
Colour CurrentColour = pColourDialog->getCurrentColour();
// Присваиваем этот цвет ярлыку
pColourLabel->setColour(Label::backgroundColourId, CurrentColour);
if(pColourDialog) delete pColourDialog;
}
}
Работа программы аналогична вышеописанным примерам и понятна из комментариев к исходному тексту.
Для доступа к классу ColourSelector необходимо в проекте Introjucer включить модуль juce_gui_extra.
В этой лекции вы научились использовать информационные окна (класс AlertWindow), а также создавать заготовки диалоговых окон и отображать их с помощью класса-обёртки DialogWindow.
Создайте программу, позволяющие открывать и просматривать файлы изображений.
Архив с исходными текстами примеров Вы можете скачать здесь
Цель лекции: Научиться создавать и использовать диалоговые окна различного назначения
В приложениях с графическим интерфейсом часто приходится выполнять действия, связанные либо с показом пользователю какой-либо информации, либо с выбором последним каких-либо параметров (выбор файлов и папок, цветов палитры и т.п.), что реализуется с помощью диалоговых окон. В законченном приложении их желательно проектировать самому, обеспечивая единство стиля всех окон программы. Именно поэтому в Juce подавляющее большинство компонентов, реализующих стандартные диалоги, представлено не законченными окнами, а их заготовками. Комбинацией подобных заготовок создаются компоненты, которые показываются пользователю с помощью объекта специального класса — DialogWindow.
Лишь простые диалоги, дающие пользователю какие-то указания (информационные окна, предупреждение об ошибках и т.п.) или позволяющие задать ему несложный вопрос, на который возможен стандартный ответ, вроде "да", "нет", "отменить", "прервать", реализуются в виде законченных окон с помощью класса AlertWindow, который мы неоднократно использовали в примерах предыдущих глав.
В данной главе на простых примерах мы рассмотрим как использование диалоговых окон, созданных с помощью AlertWindow, так и с помощью классов-заготовок.
Простейшим диалоговым окном является окно сообщения с закрывающей кнопкой (рисунок 17.1 ). Как уже упоминалось, оно создаётся вызовом метода static void JUCE_CALLTYPE AlertWindow::showMessageBox(AlertIconType iconType, const String title, const String message, const String buttonText = String::empty, Component* associatedComponent = 0), где iconType — тип отображаемой пиктограммы, title — заголовок диалога, message — его сообщение, buttonText — надпись, отображаемая на закрывающей кнопке, а associatedComponent — указатель на компонент, с которым будет ассоциировано диалоговое окно. Если указатель равен нулю, то окно будет позиционировано в центре вызывающего компонента.
Вид пиктограммы, отображаемой на диалоге, задаётся enum AlertWindow::AlertIconType, идентификатором которого являются:
NoIcon — диалог не содержит пиктограммы;QuestionIcon — пиктограмма представлена знаком вопроса;WarningIcon — пиктограмма представлена восклицательным знаком;InfoIcon — пиктограмма представлена буквой "i". Пример использования метода showMessageBox приведён в листинге 9.4.
Для отображения диалога с двумя кнопками (например, "да" и "нет", "принять", "отменить" и т.п.) используется метод static bool JUCE_CALLTYPE AlertWindow::showOkCancelBox(AlertIconType iconType, const String title, const String message, const String button1Text = String::empty, const String button2Text = String::empty, Component* associatedComponent = 0). Параметры метода аналогичны вышеописанным; button1Text и button2Text — как понятно, это надписи, отображаемые первой и второй кнопками, соответственно.
Метод возвращает истину в случае, если была нажата первая кнопка, и ложь — если вторая.
Рассмотрим использование этого метода на примере шуточной программы "Примета", знакомой многим из школьного курса информатики.
Окно программы будет включать ярлык для вывода информирующих сообщений и кнопку, нажатие на которую будет вызывать диалоговое окно (рис 17.1 ).
(рис 17.1) Программа "Примета"
Реализация компонента содержимого программы приведена в листинге 17.1 ; логика её работы определена обработчиком нажатия на кнопку buttonClicked.
#include "TCentralComponent.h"
//--------------------------------------------
#define tr(s) String::fromUTF8(s)
//--------------------------------------------
TCentralComponent::TCentralComponent() : Component("Central Component"),
pInfoLabel(0),
pQuestionButton(0)
{
// Ярлык для вывода информационного сообщения
pInfoLabel = new Label(L"Info Label",
tr("Нажмите на кнопку, чтобы начать..."));
pInfoLabel->setFont(Font(15.0000f, Font::bold));
pInfoLabel->setJustificationType(Justification::centred);
pInfoLabel->setEditable(false, false, false);
pInfoLabel->setColour(Label::textColourId, Colours::black);
pInfoLabel->setColour(Label::backgroundColourId, Colours::azure);
pInfoLabel->setColour(Label::outlineColourId, Colours::black);
addAndMakeVisible(pInfoLabel);
// Кнопка вызова диалогового окна
pQuestionButton = new TextButton(L"Question Button");
pQuestionButton->setButtonText(tr("Задать вопрос..."));
pQuestionButton->addListener(this);
addAndMakeVisible(pQuestionButton);
setSize (400, 150);
}
//------------------------------------------
TCentralComponent::~TCentralComponent()
{
// Удаляем дочерние виджеты
// и обнуляем их указатели
deleteAllChildren();
}
//------------------------------------------
void TCentralComponent::paint(Graphics Canvas)
{
Canvas.fillAll(Colours::azure);
}
//-----------------------------------------
void TCentralComponent::resized()
{
pInfoLabel->setBounds(10, 10, getWidth() - 20, 25);
pQuestionButton->setBounds(proportionOfWidth(0.5000f) - ((150) / 2),
proportionOfHeight(0.5000f) - ((25) / 2),
150, 25);
}
//------------------------------------------
void TCentralComponent::buttonClicked(Button* pButton)
{
if(pButton == pQuestionButton)
{
// Сообщение пользователю
String sMessage = String::empty;
// Задаём вопрос - вызываем диалоговое окно
bool bAnswer = AlertWindow::showOkCancelBox(AlertWindow::QuestionIcon,
tr("Примета"),
tr("Верите ли Вы в приметы?"),
tr("Да"),
tr("Нет"), 0);
// Если да...
if(bAnswer)
{
// формируем сообщение, которое будет выводиться красным цветом
sMessage = tr("Верить в приметы - плохая примета!");
pInfoLabel->setColour(Label::textColourId, Colours::red);
}
// Если нет...
else
{
// формируем сообщение, которое будет выводиться синим цветом
sMessage = tr("Поздравляю, Вы - очень разумный человек!");
pInfoLabel->setColour(Label::textColourId, Colours::blue);
}
// Показываем сообщение
pInfoLabel->setText(sMessage, false);
}
}
//-----------------------------------------------------
Внешний вид программы после нажатия на кнопку приведён на рисунке 17.2.
(рис 17.2) Программа "Примета" (показано диалоговое окно с двумя кнопками)
Для отображения диалогового окна с тремя кнопками (например, "да", "нет", "отменить") используется метод static int JUCE_CALLTYPE AlertWindow::showYesNoCancelBox(AlertIconType iconType, const String title, const String message, const String button1Text = String::empty, const String button2Text = String::empty, const String button3Text = String::empty, Component* associatedComponent = 0). Параметры button1Text, button2Text и button3Text — это надписи, отображаемые первой, второй и третьей кнопками, соответственно.
Метод возвращает следующие значения:
0 — если была нажата третья кнопка (обычно используется как кнопка "Отменить");1— если была нажата первая кнопка (обычно используется как кнопка "Да");2 — если была нажата вторая кнопка (обычно используется как кнопка "Нет").Например, следующий код
int iAnswer = AlertWindow::showYesNoCancelBox(AlertWindow::QuestionIcon,
tr("Выбор"),
tr("Внести запись в базу данных?"),
tr("Да"),
tr("Нет"),
tr("Отменить"), 0);
покажет диалог с вышеперечисленными кнопками (рисунок 17.3 ).
(рис 17.3) Диалоговое окно с тремя кнопками
Диалоговые окна для работы с файлами (открытие, сохранение) и директориями, пожалуй, используются чаще всего в современных приложениях. Библиотека Juce включает несколько компонентов для выбора файлов и каталогов; рассмотрим те из них, которые используются в качестве заготовок для создания диалоговых окон.
).
Для отображения виджета FilenameComponent мы используем "обёртку" - объект класса DialogWindow.
Рассмотрим использование компонента на примере программы, в которой пользователь с помощью диалогового окна выбирает тот или иной файл, который сохраняется в переменной ).
(рис 17.4) Программа, демонстрирующая работу FilenameComponent
Рассмотрим реализацию компонента содержимого нашего примера ().
#include "TCentralComponent.h"
//------------------------------------------
#define tr(s) String::fromUTF8(s)
//------------------------------------------
TCentralComponent::TCentralComponent() : Component("Central Component"),
pNameLabel(0),
pChooseButton(0)
{
// Ярлык для показа имени открытого файла
pNameLabel = new Label(L"Name Label", tr("Выберите файл..."));
pNameLabel->setFont(Font(15.0000f, Font::bold));
pNameLabel->setJustificationType(Justification::centred);
pNameLabel->setEditable(false, false, false);
pNameLabel->setColour(Label::textColourId, Colours::black);
pNameLabel->setColour(Label::backgroundColourId, Colours::azure);
pNameLabel->setColour(Label::outlineColourId, Colours::black);
addAndMakeVisible(pNameLabel);
// Кнопка для вызова диалога открытия файла
pChooseButton = new TextButton(L"Choose Button");
pChooseButton->setButtonText(tr("Выбрать..."));
pChooseButton->addListener(this);
addAndMakeVisible(pChooseButton);
setSize (400, 150);
}
//-----------------------------------------------
TCentralComponent::~TCentralComponent()
{
// Удаляем дочерние виджеты
// и обнуляем их указатели
deleteAllChildren();
}
//------------------------------------------------
void TCentralComponent::paint(Graphics Canvas)
{
Canvas.fillAll(Colours::azure);
}
//------------------------------------------------
void TCentralComponent::resized()
{
pNameLabel->setBounds(10, 10, getWidth() - 20, 25);
pChooseButton->setBounds(proportionOfWidth(0.5000f) - ((150) / 2),
proportionOfHeight(0.5000f) - ((25) / 2),
150, 25);
}
//-------------------------------------------------
void TCentralComponent::buttonClicked(Button* pButton)
{
if(pButton == pChooseButton)
{
// Создаём компонент для выбора файла
FilenameComponent* pFileNameDialog = new FilenameComponent(
String::empty,
ObtainedFile,
true,
false,
false,
String::empty,
String::empty,
tr("Выберите файл...")
);
// Задаём его размер (иначе его не будет видно)
pFileNameDialog->setSize(250, 25);
// Создаём "обёртку" для показа диалога...
DialogWindow::showModalDialog(tr("Выбор файла"),
pFileNameDialog,
NULL,
Colours::azure,
true,
false,
false);
// Когда файл открыт...
ObtainedFile = pFileNameDialog->getCurrentFile();
// проверяем, существует ли он
if(!(ObtainedFile == File::nonexistent))
{
// Выводим на ярлык название файла
pNameLabel->setText(ObtainedFile.getFileName(), false);
}
else
{
pNameLabel->setText(tr("Файл не выбран!"), false);
}
if(pFileNameDialog) delete pFileNameDialog;
}
}
//--------------------------------------------------------------
Как и в предыдущем примере, логика работы программы реализована в методе обработки щелчка по кнопке buttonClicked.
Вначале мы создаём собственно виджет класса FilenameComponent, конструктор которого принимает следующие параметры:
const String name — название компонента;bool canEditFilename — флаг, может ли пользователь вручную редактировать имя файла, отображаемое в выпадающем списке; в том случае, если параметр принимает значение false, изменить имя файла можно, лишь выбрав другой после нажатия кнопки обзора (кнопка с тремя точками);bool isDirectory — если параметр принимает значение true, то выбираются не файлы, а директории (папки);bool isForSaving — если параметр принимает значение true, то пользователь может выбирать несуществующие файлы, вводя их имена вручную, т.к. предполагается, что файлы выбираются для сохранения. Понятно, что для правильной работы диалога в этом случае параметр canEditFilename также должен принимать значение true;const String fileBrowserWildcard — строка-фильтр для отображения файлов по расширениям их имён, например "*.jpg;*.png". В качестве параметра может быть передана и пустая строка; в этом случае будут показаны все файлы;const String enforcedSuffix — если значение параметра — не пустая строка, то она будет автоматически добавляться ко всем именам введённых пользователем или открытых файлов;const String textWhenNothingSelected — в том случае, если в качестве параметра currentFile был передан пустой файл, то в выпадающем списке будет отображаться текст textWhenNothingSelected до тех пор, пока пользователь не выберет какой-либо файл.При нажатии на кнопку обзора вызывается диалог выбора файла, стандартный для целевой операционной системы; в случае Linux вызывается соответствующий диалог Juce, поскольку данная операционная система не имеет стандартной (встроенной) графической среды, а выбор той или иной — KDE, Gnome, Xfce и т.п. — определяется исключительно предпочтениями пользователя.
Как уже упоминалось, для отображения виджета FilenameComponent мы используем метод static int DialogWindow::showModalDialog(const String dialogTitle, Component* contentComponent, Component* componentToCentreAround, const , в который передаём указатель на этот компонент. Метод принимает следующие параметры:
const String dialogTitle — название диалога, которое будет отображаться в строке его заголовка; в нашем примере это "Выбор файла" (см. рисунок 17.4 );Component* componentToCentreAround — если указатель не равен нулю, то он указывает на компонент, который будут отображаться перед нашим диалогом;const Colour backgroundColour — цвет фона диалогового окна;bool escapeKeyTriggersCloseButton — если параметр принимает значение true, то нажатие пользователем клавиши <ESC> клавиатуры закрывает диалоговое окно;bool shouldBeResizable — флаг того, может ли пользователь изменять размеры окна потягиванием мыши;bool useBottomRightCornerResizer — флаг того, следует ли отображать виджет-ресайзер в правом нижнем углу окна.После того, как пользователь выбрал файл в диалоге, собственно его открытие осуществляется методом ), после чего мы производим проверку, не является ли файл пустым, т.е. отсутствующим на жёстком диске. Если валидность файла подтверждена, мы выводим его название без пути, получаемое с помощью метода ).
(рис 17.5) Программа, демонстрирующая работу FilenameComponent (файл открыт, его имя добавлено на ярлык программы)
Кроме того, в библиотеке Juce имеется ещё один комопнент для выбора пользователем файлов, FileChooserDialogBox. Его работу мы рассмотрим в следующем разделе, посвящённом предварительному просмотру открываемых изображений. ImagePreviewComponent, FileBrowserComponent и FileChooserDialogBox
Во время выбора пользователем тех или иных файлов зачастую возникает необходимость предварительного просмотра информации об их свойствах. Особенно часто это требуется при выборе изображений; показ уменьшенной копии графического файла, его миниатюры, значительно облегчает поиск требуемого.
Для реализации предварительного просмотра сведений об открываемом файле в библиотеке Juce имеется класс FilePreviewComponent, а для просмотра информации о графическом файле, включая его миниатюру — ImagePreviewComponent, который наследует классу первого компонента. Объект класса ImagePreviewComponent может быть использован в любых создаваемых компонентах, однако обычно указатель на него передают в качестве параметра в конструктор класса FileBrowserComponent, предназначенного для обозрения и выбора пользователем файлов для открытия и сохранения. Как и в предыдущем примере, для отображения объекта класса FileBrowserComponent необходима "оболочка". В её качестве выступает объект третьего класса — FileChooserDialogBox.
Рассмотрим использование этих трёх классов на простом примере, за основу которого мы возьмём предыдущий (см. , рис 17.5 ), однако при нажатии на кнопку "Выбрать..." будет отображаться диалоговое окно с возможностью предварительного просмотра выбираемого графического файла (рис 17.6 ).
(рис 17.6) Диалоговое окно для открытия графического файла с возможностью предварительного просмотра его миниатюры
Как и в предыдущем примере, логика работы программы реализована в обработчике события нажатия на кнопку ().
void TCentralComponent::buttonClicked(Button* pButton)
{
if(pButton == pChooseButton)
{
// Задаём в качестве стартовой директории для поиска файла
// папку "Документы" текущего пользователя
File InitialFile;
InitialFile =
InitialFile.getSpecialLocation(File::userDocumentsDirectory);
// В качестве фильтра поиска файлов задаём изображения PNG и JPG
WildcardFileFilter ImageFileFilter("*.png;*.jpg", String::empty,
tr("Файлы изображений"));
// Создаём компонент для предварительного просмотра
// открываемых файлов
ImagePreviewComponent ImageViewWidget;
// Компонент для отображения списка файлов
FileBrowserComponent FileBrowser(FileBrowserComponent::openMode |
FileBrowserComponent::canSelectFiles,
InitialFile, ImageFileFilter,
ImageViewWidget);
// Диалог для отображения FileBrowser
FileChooserDialogBox OpenFileDialog(
tr("Открыть изображение"),
tr("Выберите файл изображения, который вы хотите открыть..."),
FileBrowser, false, Colours::azure);
OpenFileDialog.setSize(600, 400);
// Если пользователь выбрал файл...
if(OpenFileDialog.show())
{
// открываем его
InitialFile = FileBrowser.getSelectedFile(0);
}
pNameLabel->setText(InitialFile.getFileName(), false);
}
}
Обзор файлов, имеющихся в той или иной папке, обеспечивает объект класса FileBrowserComponent. Его конструктор принимает следующие параметры:
int flags — флаги, описывающие поведение компонента;const File initialFileOrDirectory — начальный файл или директория, которые будут выбраны при первом открытии компонента. Если параметр принимает значение File::nonexistent, т.е. несуществующий файл, то будет открыта директория, установленная по умолчанию (в Linux это обычно домашняя папка пользователя, в Windows — папка документов);const FileFilter* fileFilter — фильтр отображения тех или иных типов файлов; в том случае, если в качестве параметра конструктор FileBrowserComponent принимает нулевой указатель, будут отображаться все файлы;FilePreviewComponent* previewComp — компонент предварительного просмотра свойств открываемых файлов. Может быть равен нулю; в этом случае файлы будут открываться без предварительного просмотра.FileBrowserComponent являются идентификаторы enum FileBrowserComponent::FileChooserFlags:openMode — обозначает, что компонент позволяет пользователю выбирать существующие файлы для их последующего открытия;saveMode — обозначает, что компонент позволяет пользователю указывать имя файла, который будет использован для сохранения в нём чего-либо;canSelectFiles — обозначает, что пользователь может выбирать файлы;canSelectDirectories — обозначает, что пользователь может выбирать директории;canSelectMultipleItems — обозначает, что пользователь может одновременно выбирать несколько элементов (папок или директорий);useTreeView — обозначает, что вместо простого списка файлов в файловом браузере будет отображаться древовидный;filenameBoxIsReadOnly — обозначает, что пользователь сможет выбирать имя того или иного файла, но не сможет вводить его вручную.В нашем примере в качестве стартовой директории мы задали папку "Документы" текущего пользователя, установили ранее созданный виджет ).
Интерфейс для принятия решения, какие именно файлы являются подходящими для выбора пользователем, реализуют классы FileFilter и WildcardFileFilter, являющийся потомком первого.
Конструктор класса FileFilter в качестве единственного параметра принимает строку — объект класса String — описывающую подходящий фильтр, например "*.jpg".
Конструктор класса WildcardFileFilter, обеспечивающего шаблоны групповых символов для файлового браузера, является более сложным и принимает три параметра:
const String fileWildcardPatterns;const String directoryWildcardPatterns;const String description.В отличие от ).
Как упоминалось, отображает файловый браузер FileBrowserComponent и управляет им класс FileChooserDialogBox. Его конструктор принимает следующие параметры:
const String title — заголовок диалогового окна;const String instructions — FileBrowserComponent; browserComponent — файловый браузер, собственно и отвечающий за выбор пользователем файлов и директорий;bool warnAboutOverwritingExistingFiles — если параметр принимает значение true, пользователь будет получать предупреждение при попытке выбора для сохранения уже существующих файлов;const Colour backgroundColour — фоновый цвет диалога.После показа диалога собственно выбор файла осуществляет метод const File FileBrowserComponent::getSelectedFile(int index) const throw(), который возвращает файл с номером index из числа выбранных пользователем.
Для создания диалога выбора цвета в библиотеке Juce используется класс ), за отображение объекта которого отвечает, как и в предыдущих примерах, класс DialogWindow.
(рис 17.7) Компонент ColourSelector
Компонент ColourSelector позволяет пользователю выбрать мышью цвет из той или иной палитры, либо ввести значения красной, зелёной и синей составляющей цвета (RGB) и прозрачности (альфа-канал) в соответствующие поля ползунков.
Внешний вид компонента можно изменять, передавая в качестве параметров конструктора его класса идентификаторы enum ColourSelector::ColourSelectorOptions:
showAlphaChannel — флаг того, что будет меняться не только RGB, но и альфа-канал цвета;showSliders — флаг отображения в диалоге ползунков, позволяющих пользователю вручную вводить значения RGB и альфа-канала;showColourspace — флаг того, будет ли отображаться шкала выбора оттенка, насыщенности и яркости цвета (HSV).По умолчанию конструктор компонента принимает следующие параметры: ).
По умолчанию виджет ColourSelector создаётся с предустановленным значением текущего цвета FFFFFFFF, что соответствует белому цвету. Но это значение можно поменять, воспользовавшись методом void ColourSelector::setCurrentColour(const .
Напротив, получить текущий цвет можно с помощью метода const .
Рассмотрим использование компонента на простом примере. Внешний вид программы и её код с небольшими изменениями заимствуем из предыдущего примера (, рис 17.2" type="example"/>, (рис 17.8) Приложение, демонстрирующее работу диалога выбора цвета
Ярлык программы окрашивается в цвет, выбираемый пользователем в виджете ).
void TCentralComponent::buttonClicked(Button* pButton)
{
if(pButton == pChooseButton)
{
// Создаём виджет выбора цвета
ColourSelector* pColourDialog = new ColourSelector();
// и устанавливаем его размер
pColourDialog->setSize(600, 400);
// Показываем диалог с созданным виджетом
DialogWindow::showModalDialog(tr("Выбор цвета"),
pColourDialog,
NULL,
Colours::azure,
true,
false,
false);
// Сохраняем текущий цвет виджета в переменной
// после закрытия диалога
Colour CurrentColour = pColourDialog->getCurrentColour();
// Присваиваем этот цвет ярлыку
pColourLabel->setColour(Label::backgroundColourId, CurrentColour);
if(pColourDialog) delete pColourDialog;
}
}
Работа программы аналогична вышеописанным примерам и понятна из комментариев к исходному тексту.
Для доступа к классу ColourSelector необходимо в проекте Introjucer включить модуль juce_gui_extra.
В этой лекции вы научились использовать информационные окна (класс AlertWindow), а также создавать заготовки диалоговых окон и отображать их с помощью класса-обёртки DialogWindow.
Создайте программу, позволяющие открывать и просматривать файлы изображений.
Архив с исходными текстами примеров Вы можете скачать здесь
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.