Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Программирование с использованием gtkmm 3. Виджет области рисования (DrawingArea)

Оригинал: Programming with gtkmm 3
Авторы: Murray Cumming, Bernhard Rieder, Jonathon Jongsma, Ole Laursen, Marko Anastasov, Daniel Elstner, Chris Vine, David King, Pedro Ferreira, Kjell Ahlstedt
Перевод: А.Панин

17.5. Вывод текста

17.5.1. Вывод текста с помощью библиотеки Pango

Вывод текста осуществляется с помощью областей вывода текста Pango (Pango Layouts). Простейшим способом создания экземпляра класса области вывода текста Pango Pango::Layout является вызов функции Gtk::Widget::create_pango_layout(). После создания область вывода текста Pango может использоваться для различных манипуляций с текстом, включая изменение текста, шрифта, и.т.д. Наконец, область вывода текста Pango может быть размещена в области рисования с помощью метода Pango::Layout::show_in_cairo_context().

17.5.2. Пример

Ниже приведен пример программы, которая с помощью области рисования выводит текст, часть которого является перевернутой. Глава "Печать" содержит другой пример вывода текста.

Рисунок 17-6: Область рисования - Текст
Область рисования - Текст

Исходный код

Файл: myarea.h (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: mayarea.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: main.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

17.6. Вывод существующих изображений

Существует метод для вывода объекта буфера пикселей на основе класса Gdk::Pixbuf с помощью контекста Cairo на основе класса Cairo::Context. Класс буфера пикселей Gdk::Pixbuf является удобной оберткой над набором пикселей, который может формироваться на основе прочитанных из файлов изображений данных и подвергаться различным модификациям впоследствии.

Самым часто используемым способом создания объектов на основе класса Gdk::Pixbuf, скорее всего, является вызов метода Gdk::Pixbuf::create_from_file(), который позволяет прочитать данные из файла изображения, такого, как файл формата PNG, в готовый для вывода буфер пикселей.

Данные буфера пикселей на основе класса Gdk::Pixbuf могут быть выведены с помощью контекста Cairo после объявления этого буфера источником данных шаблона изображения контекста Cairo путем вызова метода Gdk::Cairo::set_source_pixbuf(). После этого изображение может прорисовываться либо путем вызова метода Cairo::Context::paint() (для прорисовки всего изображения), либо путем вызова методов Cairo::Context::rectangle() и Cairo::Context:fill() (для прорисовки изображения в заданной прямоугольной области). Функция set_source_pixbuf() не является методом класса Cairo::Context. Она принимает экземпляр класса Cairo::Context в качестве первого параметра.

Ниже приведен простой фрагмент кода с реализацией всех описанных выше операций. (Учтите, что в большинстве случаев вам не придется загружать изображение каждый раз при обработке сигнала перерисовки! Данный фрагмент кода всего лишь является обобщением описанной выше методики вывода изображений.)
bool MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
  Glib::RefPtr<Gdk::Pixbuf> image = Gdk::Pixbuf::create_from_file("myimage.png");
  // Прорисовка изображения в точке с координатами 110, 90 за исключением 10 пикселей на внешних границах.
  Gdk::Cairo::set_source_pixbuf(cr, image, 100, 80);
  cr->rectangle(110, 90, image->get_width()-20, image->get_height()-20);
  cr->fill();
  return true;
}

17.6.1. Пример

Ниже приведен пример простой программы, предназначенной для вывода изображения в области рисования.

Рисунок 17-7: Область рисования - Изображение
Область рисования - Изображение

Исходный код

Файл: myarea.h (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: myarea.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: main.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

17.7. Пример приложения: часы на основе Cairo

После того, как мы рассмотрели основные методы рисования с помощью библиотеки Cairo, давайте попытаемся обобщить полученную информацию и создать простое приложение, которое выполняет полезную функцию. В примере библиотека Cairo используется для создания специального виджета часов. Часы имеют секундную, минутную и часовую стрелки и обновляют их положение каждую секунду.

Рисунок 17-8: Область рисования - Часы
Область рисования - Часы

Исходный код

Файл: clock.h (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: clock.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: main.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Как и раньше, в данном случае практически все интересные вещи реализованы в рамках обработчика сигналов on_draw(). Перед тем, как мы будем исследовать обработчик сигналов перерисовки, следует обратить внимание на то, что конструктор класса виджета Clock устанавливает функцию обработчика on_timeout() для таймера с временем срабатывания в 1000 миллисекунд (или 1 секунду). Это означает, что функция on_timeout() будет вызываться один раз в секунду. Единственной задачей этой функции является установка флага устаревания изображения окна для того, чтобы принудить gtkmm перерисовать его.

Теперь давайте рассмотрим код, в рамках которого выполняются сами операции рисования. Первая часть функции on_draw() на данный момент должна быть достаточно знакомой. В данном примере снова производится масштабирование координатной системы до единичного квадрата с целью упрощения рисования часов с использованием процентного соотношения размеров окна, поэтому изображение будет автоматически масштабироваться при изменении размеров окна. Более того, впоследствии производится еще одно масштабирование координатной системы таким образом, что точка с координатами (0,0) находится в самом центре окна.

Функция Cairo::Context::paint() в данном случае используется для установки цвета фона окна. Эта функция не принимает аргументов и заполняет текущую поверхность (или ограниченную часть поверхности) активным на данный момент цветом. Выполнив установку цвета фона окна, мы рисуем внешнюю окружность циферблата часов и закрашиваем ее белым цветом с последующей обводкой этой окружности черным цветом. Обратите внимание на то, что при выполнении всех описанных действий используются варианты функций с суффиксами _preserve для сохранения текущего контура, причем впоследствии этот же контур используется для выравнивания будущих линий с гарантией того, что ни одна из этих линий не пересечет внешнюю окружность циферблата часов.

После изображения внешней окружности часов мы обходим циферблат и рисуем деления для каждого часа, причем деления для 12, 3, 6 и 9 часов имеют больший размер. Теперь мы наконец готовы к реализации функции отображения текущего времени наших часов, которая заключается в простом получении текущих значений часов, минут и секунд и рисовании стрелок под корректными углами.


Следующий раздел : Механизм захвата и перемещения данных (Drag and Drop).