В прошлом выпуске мы начали писать программу для просмотра
графических файлов 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 - это такая структура, которая содержит основную информацию о
графическом изображении:
число бит на пиксел,
число цветов,
палитру,
размеры изображения,
конечно же само изображение,
и некоторые другие вспомогательные параметры.
Из 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 кб]