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

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

  Все выпуски  

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



Image Viewer 1.1

В прошлом выпуске мы начали писать программу для просмотра графических файлов image_viewer. Был создан только каркас.
На этот раз добавим диалог  выбора графического файла, проверим файл на принадлежность к изображениям, и отобразим в текстовой метке[в нижней части главного окна] информацию о картинке.

Добавим обработчик элемента меню OpenFile в функцию menuitem_response в файле create_menu.c:

// обработчик выбора элемента меню
static void  menuitem_response (GtkMenuItem *menuitem,gpointer user_data)
{
    // какой элемент меню был выбран
    gchar *menu_name = (gchar*)user_data;
    printf("menuitem %s\n",menu_name);// печатаем в консоль - для отладки
    if (!strcmp(menu_name,"Quit"))// ВЫХОД
        gtk_widget_destroy(window);
    else
    if (!strcmp(menu_name,"OpenFile"))// открыть файл
    {
        // диалог выбора файла
        select_image_file();
        return;
    }
}
Синим цветом выделены изменения.  Теперь при выборе элемента меню OpenFile будет вызываться функция select_image_file().

Вот её код:
static void select_image_file(void)
{
    // Создать диалог открытия файла с двумя кнопками 'Open' и 'Cancel'
    GtkWidget *dialog_file_choose = gtk_file_chooser_dialog_new("Выберите графический файл",
                                                        GTK_WINDOW(window),GTK_FILE_CHOOSER_ACTION_OPEN,
                                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                                        GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                                        NULL);
    // выбрать стартовый каталог для выбора файла
    {
        gchar *home_dir = (gchar*)g_get_home_dir();
        gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog_file_choose),home_dir);
    }
    // запуск диалога выбора файла
    if (gtk_dialog_run (GTK_DIALOG (dialog_file_choose)) == GTK_RESPONSE_ACCEPT)// если нажали клавишу 'Open'
    {
        char *filename_ansi;
        // Узнаём имя файла, причём в кодировке системы
        filename_ansi = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog_file_choose));
        // открываем картинку
        open_file(filename_ansi);
        g_free (filename_ansi);
    }
    //
    gtk_widget_destroy (dialog_file_choose);
}


Функция gtk_file_chooser_dialog_new() создаёт окно для выбора файла на диске.
Первый параметр - это заголовок окна.
Родительский виджет - главное окно window,  поэтому наш диалог будет отображён в центре основного окна.
GTK_FILE_CHOOSER_ACTION_OPEN говорот, что тип диалога - открытие существующего файла.
В нашем диалоге снизу будет две кнопки: Открыть (GTK_STOCK_OPEN) и Отмена  (GTK_STOCK_CANCEL).
При нажатии кнопки Открыть диалог вернёт GTK_RESPONSE_ACCEPT, а при Отмене - GTK_RESPONSE_CANCEL.

Сделаем чтобы первоночальный выбранный каталог в диалоге был домашним каталогом  пользователя.
С помощью g_get_home_dir()  мы его узнаем, а потом зададим для диалога:
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog_file_choose),home_dir);
Для Windows под домашним каталогом пользователя подразумевается каталог "Мои Документы".
Но диалоговое окно только создано, а не запущено.
Диалог, в нашем случае модальный, появляется на экране после вызова gtk_dialog_run() и функция вернёт значение только после закрытия диалога.
Если нажмём кнопку Открыть (диалог вернёт GTK_RESPONSE_ACCEPT), тогда узнаём выбранный файл в диалоге:
filename_ansi = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog_file_choose));
и запускаем функцию анализа файла open_file():

// открываем картинку
gboolean open_file(char *filename_ansi)
{
    guint cx,cy;
    GdkPixbufFormat *info_pbuf=NULL;
    gchar *filename_utf8;
    gchar *only_filename;
    gchar *str;
    // переводим в кодировку UTF8, ведь имя файла будет отображено на экране
    filename_utf8 = g_filename_to_utf8(filename_ansi, -1, NULL, NULL, NULL);
    // узнать имя файла, без путей
    only_filename = g_path_get_basename(filename_utf8);
    // если уже есть картинка, то удаляем её
    if(pict)            g_object_unref (pict);
    pict = NULL;
    // получаем информацию о картинке
    info_pbuf = gdk_pixbuf_get_file_info(filename_ansi,&cx,&cy);
    if(info_pbuf)// файл распознался как картинка
        pict = gdk_pixbuf_new_from_file(filename_ansi, NULL);
    // обновить информацию о файле
    if(pict)
    {
        int bits = gdk_pixbuf_get_bits_per_sample(pict);
        gboolean alpha = gdk_pixbuf_get_has_alpha(pict);
        str = g_strdup_printf("Файл: '%s'    Размер: %dx%d   Глубина цвета: %d бит    Прозрачность:%s",only_filename,cx,cy,bits,(alpha)?"есть":"нет");
    }
    else
        str = g_strdup_printf("Файл: '%s'  не является распознанной картинкой",only_filename);
    gtk_label_set_text(GTK_LABEL(label_info),str);
   
    g_free(filename_utf8);
    g_free(only_filename);
    g_free(str);
    if(!pict)    return FALSE;
    return TRUE;
}


Функция open_file() расположена не в create_menu.c, а в image_viewer.с, поэтому объявим её прототип в image_viewer.h
Первым делом переводим имя файла в кодировку UTF8, иначе с русскими буквами при отобрадении на экране будут проблемы, вернее символы совсем не будут отображаться.
filename_utf8 = g_filename_to_utf8(filename_ansi, -1, NULL, NULL, NULL);
Отображать имя файла с полным путём на экране может быть длинным, поэтому получим только одно имя:
only_filename = g_path_get_basename(filename_utf8);
Проверим, графический ли это файл, а заодно узнаем его размеры:
info_pbuf = gdk_pixbuf_get_file_info(filename_ansi,&cx,&cy);
Если структура info_pbuf не нулевая, значит файл - распознанная картинка.
Список файлов, поддерживаемых GTK+ довольшо широк: ANI, BMP, GIF, ICO, JPEG, PCX, PNG, PNM, RAS, TGA, TIFF, WBMP, XBM, XPM.  В GTK 2.10.14 появились WMF и SVG.

Создаём GdkPixbuf:
pict = gdk_pixbuf_new_from_file(filename_ansi, NULL);

GdkPixbuf - это такая структура, которая содержит основную информацию о графическом изображении:
число бит на пиксел,
число цветов,
палитру,
размеры изображения,
конечно же само изображение,
и некоторые другие вспомогательные параметры.

Из GdkPixbuf узнаём число бит на пиксел в картинке:
int bits = gdk_pixbuf_get_bits_per_sample(pict);
а также наличие альфа-канала, то есть прозрачность.
gboolean alpha = gdk_pixbuf_get_has_alpha(pict);

Информацию о файле выводим в текстовую метку на экране:
gtk_label_set_text(GTK_LABEL(label_info),str);

 

Готовое приложение вместе с исходными кодами доступно по ссылке: image-viewer1.1.tar.gz [37 кб]


В избранное