Отправляет email-рассылки с помощью сервиса Sendsay

Практические советы по GTK+

  Все выпуски  

Практические советы по GTK+



Image Viewer 1.3

В этом выпуске продолжим писать программу просмотра графических файлов - image_viewer. 
В этот раз займёмся выводом текста на экран в различных режимах и с форматированием. В GTK+ формированием и отображением текста занимается целая библиотека - Pango. Ещё есть векторная графическая библиотека Сairo, но она позволяет уже выводить текст под разными углами, но пока мы заёмёмся Pango. С помощью библиотеки Pango можно выводить текст в кодировке UTF8, таким образом текст может быть интернациональным.

Часть 1.

Рассмотрим, как можно вывести текст в область рисования с помощью функций Pango.

Пока графический файл не открыт, будем выводить текст посредине экрана:
Выберите картинку в меню File->Open File

Для этого в файл image_viewer.c в функцию перерисовки картинки map_expose() вставим код:
// выбираем цвет для рисования - красный;
color.red = 65535;
color.green= 0;
color.blue = 0;
gdk_gc_set_rgb_fg_color (gc, &color);
{
        int size_x,size_y;
        char *text="Выберите картинку в меню File->Open File";//Файл->Открыть файл
        PangoFontMap *fontmap=NULL;
        PangoLayout *layout = NULL;
        PangoFontDescription *desc;
        GdkScreen *screen = gdk_screen_get_default();
        PangoContext *context = (PangoContext*)gdk_pango_context_get_for_screen(screen);
        // шрифт
        desc = pango_context_get_font_description(context);
        // меняем параметры шрифта
        pango_font_description_set_family(desc,"Arial");
        pango_font_description_set_style(desc,PANGO_STYLE_ITALIC);//PANGO_STYLE_NORMAL
        pango_font_description_set_weight(desc,PANGO_WEIGHT_BOLD);
        pango_font_description_set_size(desc,16*PANGO_SCALE);
        pango_context_load_font(context,desc);
        // Pango слой       
        layout = pango_layout_new(context);
        pango_layout_set_text(layout,text,(int)strlen(text));
        pango_layout_get_size(layout,&size_x,&size_y);// узнаём размеры текста для вывода на экран
        // переводим в пиксели
        size_x/=PANGO_SCALE;
        size_y/=PANGO_SCALE;
        // отрисовываем текст на экран
        gdk_draw_layout(draw_area->window,gc,dx/2-size_x/2,dy/2-size_y/2,layout);
        // очистка памяти
        g_object_unref(context);
        g_object_unref(layout);
}

Для вывода текста создаётся слой Pango - PangoLayout, в который помещаем текст, а затем слой Pango отображаем в GDK окне виджета draw_area.
А теперь поподробнее:
Для начала создаём контекст Pango - PangoContext, который нужен для создания PangoLayout.

GdkScreen *screen = gdk_screen_get_default();
P
angoContext *context = (PangoContext*)gdk_pango_context_get_for_screen(screen);

Узнаём  шрифт по умолчанию для созданного контекста.

// шрифт
desc = pango_context_get_font_description(context);

Потом задаём характеристики шрифта - имя шрифта, стиль, жирность и размер.

pango_font_description_set_family(desc,"Arial");
pango_font_description_set_style(desc,PANGO_STYLE_ITALIC);
pango_font_description_set_weight(desc,PANGO_WEIGHT_BOLD);
pango_font_description_set_size(desc,16*PANGO_SCALE);

Затем создаём PangoLayout из созданного контекста,

layout = pango_layout_new(context);

добавляем в него текст.

pango_layout_set_text(layout,text,(int)strlen(text));

Чтобы вывести текст точно по центру окна, нужно знать размены окна и размеры текста.
Определяем размеры текста:

pango_layout_get_size(layout,&size_x,&size_y);

Остаётся только отобразить текст на экране:

gdk_draw_layout(draw_area->window,gc,dx/2-size_x/2,dy/2-size_y/2,layout);

Напоследок почистим память:

g_object_unref(context); g_object_unref(layout);

 

Часть 2.

Форматированный текст может быть выведен и в обычных текстовых метках. Для этого текст должен быть описан с использованием тега <span> (подобно языку HTML)
Вот пример использования тега <span>: (строка с жирным и перечёркнутым тёмно-синей чертой текстом)

"<span weight="bold" strikethrough="true" strikethrough_color="darkblue">Bold and dark blue text</span>"

Для того, чтобы текстовая метка не вывела всё это форматирование в простом виде, текст добавлять нужно не с помощью gtk_label_set_text(), а специальной функцией:

void gtk_label_set_markup(GtkLabel *label,const gchar *str);

Которая выводит текст  разбирая содержимое тега <span>. Вот его описание:

Атрибут тега span

Описание

font_desc  Строка с описанием шрифта, например "Sans Italic 12"; любой span атрибут может быть задан здесь.
font_family  Имя шрифта
face  То же самое, что и font_family
size

 Размер шрифта, может принимать относительные значения: 'smaller' или 'larger' и абсолютные значения: 'xx-small', 'x- small', 'small', 'medium', 'large', 'x-large', 'xx-large'.
 Также размер можно указывать в цифрах, но только в масштабе x1024. Например для шрифта 12.5, size='12800' (12.5x1024=12800), но проще использовать font_desc='12.5' .

style  Наклон шрифта, может принимать значения:  'normal', 'oblique', 'italic'
weight  Жирность шрифта, может принимать значения: 'ultralight', 'light', 'normal', 'bold', 'ultrabold', 'heavy', или числа
variant  'normal' или 'smallcaps'
stretch  Ширина шрифта, может принимать значения:'ultracondensed', 'extracondensed', 'condensed','semicondensed', 'normal', 'semiexpanded', 'expanded','extraexpanded', 'ultraexpanded'
foreground  Цвет символов.В виде RGB, один и тот же цвет может быть определен как '#00FF00' или '#0F0' или 'green'
background  Цвет фона.В виде RGB, один и тот же цвет может быть определен как '#FF0000' или '#F00' или 'red'
underline  Нижнее подчёркивание, может принимать значения: 'single', 'double', 'low', 'none'
underline_color  Цвет нижнего подчёркивания, в виде RGB,  без underline не имеет смысла
rise  Вертикальное смещение текста, положительное вверх, отрицательное вниз.
strikethrough  Перечёркивание текста, может принимать значения: 'true' or 'false'
strikethrough_color  Цвет линии перечёркивания текста, в виде RGB,  без strikethrough не имеет смысла
fallback  Принимает значения: 'true'(по умолчанию) or 'false'. Можно ли выбрать шрифт с другими характеристиками, если заданный не доступен в системе. Если fallback='false', то при недоступности шрифта может быть выдана ошибка, а если fallback='true' - буден выбран максимально похожий шрифт.
lang  Код используемого языка
Вместо тега <span> можно использовать и некоторые другие, с меньшими возможностями, например <b>bold</b> означает жирный текст. Описание дополнительных тегов дано в таблице:

Дополнительные теги

b

Жирный текст

big

Увеличить шрифт, тоже самое, что и <span size="larger">

i

Наклон

s

Перечёркивание

sub

Опускание вниз текста

sup

Подъём вверх текста

small

Уменьшить шрифт, тоже самое, что и <span size="smaller">

tt

Шрифт с равномерными сомволами по ширине(Monospace)

u

Нижнее подчёркивание

В качестве примера использования новой возможности добавим диалог "О программе" и напишем в нём форматированный текст.

В обработчик меню menuitem_response() добавим перехват выбора меню About:

 if (!strcmp(menu_name,"About"))
 {
    // диалог - о программе;
    dlg_about(GTK_WIDGET(window));
 }

Вот код диалоговой функции:

// диалог - О программе
int dlg_about(GtkWidget *parent)
{
    GtkWidget *dialog=NULL;
    GtkWidget *vbox;
    GtkWidget *label;
    gchar    *str;
    // создаём диалог с одной кнопкой OK   
    dialog = gtk_dialog_new_with_buttons("О программе",(GtkWindow*)parent,
                                            GTK_DIALOG_MODAL|
                                            GTK_DIALOG_DESTROY_WITH_PARENT|GTK_DIALOG_NO_SEPARATOR,
                                            GTK_STOCK_OK,
                                            GTK_RESPONSE_OK,
                                            NULL);
   
    vbox = gtk_vbox_new (FALSE, 4);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
    // vbox упаковываем в верхнюю часть диалога dialog->vbox;
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), vbox, TRUE, TRUE, 0);
   
    // заполнение диалога
    // Создание строки
    str = g_strdup_printf("<span foreground=\"#00f\" weight=\"bold\" size=\"x-large\">Image Viewer v.%s</span>",VERSION);
    // Programm name;
    label = gtk_label_new(NULL);
    gtk_label_set_markup(GTK_LABEL (label),str);
    g_free(str);
    gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 10);
   
    // выполнение диалога;
    gtk_widget_show_all( dialog );
    gtk_dialog_run (GTK_DIALOG (dialog));
    gtk_widget_destroy(dialog);
    return 0;
}

Здесь нет ничего необычно,  создаётся окно dialog, упаковываем в него текстовую метку label, отображаем диалог и запускаем ожидание нажатия клавиши кнопки OK (или закрытия диалога). Вот строка, которую будем выводить в текстовой метке: (Синий текст, жирый и большой.)

str = g_strdup_printf("<span foreground=\"#00f\" weight=\"bold\" size=\"x-large\">Image Viewer v.%s</span>",VERSION);

 
Исходные коды приложения доступны по ссылке: image-viewer1.3.tar.gz [18 кб]

Все вопросы, пожелания, можно отсылать по адресу: comp.soft.prog.gtk-owner@subscribe.ru


В избранное