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

Шрифты и строки

< Лекция 5 || Лекция 6: 1234 || Лекция 7 >
Аннотация: В этой лекции вы ознакомитесь со строковым типом данных (класс String), а также с управлением отображения текстовой информации в программах Juce (класс Font).

Цель лекции: Дать базовые представления о работе с текстом в Juce

Основным способом "общения" компьютерной программы с пользователем является вывод текстовых сообщений (диалоговые окна, надписи на ярлыках, панелях и т.п.). Внешний вид таких сообщений задаётся тем или иным шрифтом.

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

Для работы со шрифтами в Juce существует специальный класс, Font. Мы уже использовали его в предыдущих лекциях. Объект этого класса передаётся в качестве параметра в метод setFont() различных компонентов (Label, TextEditor, HyperlinkButton и др.). Класс Component метода setFont() не имеет.

Основные свойства компьютерных шрифтов заимствованы из типографского дела. Ими являются следующие:

  • Typeface — гарнитура или внешний вид шрифта, определяемый набором символов, имеющих стилистическое единство. Возвращается методом Typeface* Font::getTypeface() const. Если нужно получить не сам объект гарнитуры, а только её название для текущего шрифта (строку), то можно воспользоваться методом const String& Font::getTypefaceName() const throw().
  • Высота шрифта в пикселях. Возвращается методом float Font::getHeight() const throw().
  • Стиль шрифта: нормальный, полужирный, курсив и подчёркнутый. Класс Font включает нумерованный список enum FontStyleFlags {plain = 0, bold = 1, italic = 2, underlined = 4}, элементы которого соответствуют вышеперечисленным стилям.
  • Если программа Juce не может найти шрифт с заданной комбинацией свойств, то используется другой шрифт, далеко не всегда близкий по свойствам. Поэтому можно воспользоваться методами класса Font для получения названий гарнитур шрифтов, использующихся по умолчанию в данной операционной системе:
  • static const String Font::getDefaultMonospacedFontName() — возвращает имя гарнитуры моноширинного рубленного шрифта, используемого по умолчанию;
  • static const String Font::getDefaultSerifFontName() — возвращает имя гарнитуры шрифта с засечками (Serif), используемого по умолчанию;
  • static const String Font::getDefaultSansSerifFontName() — возвращает имя гарнитуры рубленного шрифта (Sans), используемого по умолчанию.

По умолчанию для всех компонентов Juce задаётся нормальный (стиль plain) шрифт гарнитуры Sans размером 15 пикселей.

В большинстве текстовых редакторов задаётся кегль шрифта — размер высоты символов, измеряемый в типографских пунктах. В Juce высота шрифта, задаваемая методом void Font::setHeight(float newHeight), как упоминалось, измеряется в пикселях. Получить её, исходя из заданного пользователем кегля в типографских пунктах, можно по формуле:

Высота (пиксели) = Кегль (пункты) ? DPI / 72,

где DPI (dots per inch) — число пикселей на дюйм, зависящее от характеристик монитора.

Рассмотрим работу со шрифтами на примере демонстрационного приложения ( рис. 6.1).

Демонстрационное приложение свойств шрифта

Рис. 6.1. Демонстрационное приложение свойств шрифта

В приложении текст из поля ввода (TextEditor* pFontViewer) отображается шрифтом, гарнитура и размер которого выбираются пользователем из выпадающих списков (ComboBox* pFontsBox и ComboBox* pFontSizeBox, соответственно). Стиль шрифта задаётся переключением радокнопок: ToggleButton* pNormalButton — для нормального стиля, ToggleButton* pBoldButton — для полужирного стиля, ToggleButton* pItalicButton — для курсива. Текущий шрифт, используемый для отображения текста в поле ввода, будем сохранять в закрытом члене класса компонента содержимого, Font CurrentFont ( пример 6.1).

#ifndef _TCentralComponent_h_
#define _TCentralComponent_h_
//-------------------------------------------------------
#include "../JuceLibraryCode/JuceHeader.h"
//-------------------------------------------------------
// Класс компонента содержимого.
// Наследует классы слушателей выпадающих списков и кнопок
class TCentralComponent  : public Component,
          public ComboBoxListener,
          public ButtonListener
{
public:
  TCentralComponent();
  ~TCentralComponent();

  void paint(Graphics&);
  void resized();
  // Функция, отслеживающая изменения в выпадающих списках
  void comboBoxChanged(ComboBox*);
  // Функция, отслеживающая щелчки по кнопке
  void buttonClicked(Button*);

private:
  // Текущий шрифт текста, отображаемого в TextEditor
  Font CurrentFont;
  
  // Многострочное поле ввода
  TextEditor* pFontViewer;
  Label* pFontNameLabel;
  // Выбор гарнитуры шрифта
  ComboBox* pFontsBox;
  Label* pFontSizeLabel;
  // Выбор размера (кегля) шрифта
  ComboBox* pFontSizeBox;
  Label* pFontStyleLabel;
  GroupComponent* pFontGroup;
  // Радиокнопка выбора стиля нормального шрифта
  ToggleButton* pNormalButton;
  // Радиокнопка выбора стиля полужирного шрифта
  ToggleButton* pBoldButton;
  // Радиокнопка выбора стиля курсива
  ToggleButton* pItalicButton;

  // Предотвращает создание копии конструктора и оператора =
  TCentralComponent(const TCentralComponent&);
  const TCentralComponent& operator= (const TCentralComponent&);
};
//----------------------------------------------------
#endif
Листинг 6.1. Объявление класса компонента содержимого TCentralComponent (файл TCentralComponent.h)

Реализация класса компонента содержимого довольно велика, поэтому рассмотрим её по частям. В конструкторе класса добавим и сделаем видимыми поле ввода, ярлыки, выпадающие списки, групповой блок (GroupComponent* pFontGroup), объединяющий ранее упоминавшиеся радиокнопки ( пример 6.2).

#include "TCentralComponent.h"
//--------------------------------------------------------
#define tr(s) String::fromUTF8(s)
//--------------------------------------------------------
TCentralComponent::TCentralComponent() : Component("Central Component"),
           pFontViewer(0),
           pFontNameLabel(0),
           pFontsBox(0),
           pFontSizeLabel(0),
           pFontSizeBox(0),
           pFontStyleLabel(0),
           pFontGroup(0),
           pNormalButton(0),
           pBoldButton(0),
           pItalicButton(0)
{
  pFontViewer = new TextEditor("FontViewer");
  // Поле ввода - многострочное
  pFontViewer->setMultiLine(true);
  // Новая строка при нажатии клавиши <ENTER>
  pFontViewer->setReturnKeyStartsNewLine(true);
  // Запрет на редактирование
  pFontViewer->setReadOnly(true);
  // Показать полосы прокрутки
  pFontViewer->setScrollbarsShown(true);
  pFontViewer->setText(tr("Съешь же ещё этих мягких французских булок да выпей чаю.\n1234567890\n`~@#$%^&*()-_=+\\|{[]};:'\"/?"));
  addAndMakeVisible(pFontViewer);

  pFontNameLabel = new Label("FontNameLabel", tr("Гарнитура (вид) шрифта"));
  pFontNameLabel->setFont(Font(15.0000f, Font::plain));
  pFontNameLabel->setJustificationType(Justification::centredLeft);
  pFontNameLabel->setEditable(false, false, false);
  pFontNameLabel->setColour(Label::textColourId, Colours::black);
  pFontNameLabel->setColour(Label::backgroundColourId,
          Colour(Colours::azure));
  addAndMakeVisible(pFontNameLabel);
  
  pFontsBox = new ComboBox("FontsBox");
  // Запрет на редактирование текста в выпадающем списке
  pFontsBox->setEditableText(false);
  // Выравнивание теста по левому краю и центру виджета
  pFontsBox->setJustificationType(Justification::centredLeft);
  pFontsBox->setTextWhenNothingSelected(tr("Стандартный шрифт"));
  // Устанавливаем в качестве слушателя списка
  // сам компонент-контейнер
  pFontsBox->addListener (this);
  addAndMakeVisible(pFontsBox);
  
  // Получаем имена системных шрифтов, сохраняем их 
  // в строковом массиве...
  StringArray sSystemFonts = Font::findAllTypefaceNames();
  // и добавляем в выпадающий список
  for(int i = 0; i < sSystemFonts.size(); i++)
  {
    pFontsBox->addItem(sSystemFonts[i], i + 1);
  }

  pFontSizeLabel = new Label("FontSizeLabel", tr("Размер (кегль) шрифта"));
  pFontSizeLabel->setFont(Font(15.0000f, Font::plain));
  pFontSizeLabel->setJustificationType(Justification::centredLeft);
  pFontSizeLabel->setEditable(false, false, false);
  pFontSizeLabel->setColour(Label::textColourId, Colours::black);
  pFontSizeLabel->setColour(Label::backgroundColourId,
          Colour(Colours::azure));
  addAndMakeVisible(pFontSizeLabel);
  
  pFontSizeBox = new ComboBox("FontSizeBox");
  pFontSizeBox->setEditableText(false);
  pFontSizeBox->setJustificationType(Justification::centredLeft);
  pFontSizeBox->setTextWhenNothingSelected(tr("Размер по умолчанию"));
  pFontSizeBox->addItem("8", 1);
  pFontSizeBox->addItem("9", 2);
  pFontSizeBox->addItem("10", 3);
  pFontSizeBox->addItem("11", 4);
  pFontSizeBox->addItem("12", 5);
  pFontSizeBox->addItem("13", 6);
  pFontSizeBox->addItem("14", 7);
  pFontSizeBox->addItem("15", 8);
  pFontSizeBox->addItem("16", 9);
  pFontSizeBox->addItem("17", 10);
  pFontSizeBox->addItem("18", 11);
  pFontSizeBox->addItem("19", 12);
  pFontSizeBox->addItem("20", 13);
  // Устанавливаем в качестве слушателя списка
  // сам компонент-контейнер
  pFontSizeBox->addListener (this);
  addAndMakeVisible(pFontSizeBox);
  
  pFontStyleLabel = new Label("FontStyleLabel", tr("Стиль шрифта"));
  pFontStyleLabel->setFont(Font(15.0000f, Font::plain));
  pFontStyleLabel->setJustificationType(Justification::centredLeft);
  pFontStyleLabel->setEditable(false, false, false);
  pFontStyleLabel->setColour(Label::textColourId, Colours::black);
  pFontStyleLabel->setColour(Label::backgroundColourId,
          Colour(Colours::azure));
  addAndMakeVisible(pFontStyleLabel);
  
  pFontGroup = new GroupComponent("FontGroup", tr("Шрифт"));
  pFontGroup->setTextLabelPosition(Justification::centredLeft);
  addAndMakeVisible(pFontGroup);
  
  pNormalButton = new ToggleButton("NormalButton");
  pNormalButton->setButtonText(tr("Нормальный"));
  // Устанавливаем в качестве слушателя кнопки
  // сам компонент-контейнер
  pNormalButton->addListener(this);
  // Радиокнопка отмечена
  pNormalButton->setToggleState(true, false);
  pNormalButton->setRadioGroupId(1234);
  addAndMakeVisible(pNormalButton);
  
  pBoldButton = new ToggleButton("BoldButton");
  pBoldButton->setButtonText(tr("Полужирный"));
  pBoldButton->addListener(this);
  // Радиокнопка не отмечена
  pBoldButton->setToggleState(false, false);
  pBoldButton->setRadioGroupId(1234);
  addAndMakeVisible(pBoldButton);
  
  pItalicButton = new ToggleButton("ItalicButton");
  pItalicButton->setButtonText(tr("Курсив"));
  pItalicButton->addListener(this);
  pItalicButton->setToggleState(false, false);
  pItalicButton->setRadioGroupId(1234);
  addAndMakeVisible(pItalicButton);

  setSize (600, 400);
}
//------------------------------------------------------
Листинг 6.2. Конструктор класса TCentralComponent (файл TCentralComponent.cpp)
< Лекция 5 || Лекция 6: 1234 || Лекция 7 >