Программирование GNOME в Linux с использованием GTK+ .
Автор : Subhasish Ghosh
Перевод : Владимир Меренков .
1. Что такое GNOME вообще? Введение.
Перед тем, как входить в интересующий нас мир программирования для Gnome в Linux, давайте попытаемся понять, к чему на самом деле имеет отношение Gnome. GNOME это акроним "GNU's Not Unix Network Object Model Environment". Хотя это звучить немного сложновато, Gnome -- это программный проект с простой целью: Обеспечить всех пользователей Linux черезвычайно дружественной , но в то же время мощной и функционально полной реализации среды графического рабочего стола.. В последних релизах Linux от Red Hat и Debian GNOME --- устанавливаемый по умолчанию десктоп (рабочий стол).
Для более определенной информации о GMOME и ее разнообразных и замечательных особенностях, обязательно посетите страницу проекта GNOME на http://www.gnome.org/, которая предоставляет читателям изобилие информации, включая онлайновую документацию, новости; оттуда же можно скачать бинарные файлы и исходники GNOME, совместимые с большинством Linux систем.
Теперь давайте посмотрим на GNOME с двух точек зрения, "программиста Linux" и "Linux-администратор". Основной вопрос, который приходит в голову: думают ли они и чувствуют одно и то же, когда говорят о GNOME? Ответ не так прост, как сам вопрос. Большинство Linux администраторов являются действующими программистами или были таковыми в прошлом, что делает ответ на вопрос совсем сложным. Для среднего системного администратора Linux среда GNOME предоставляет изобилие инструментов, делающих его/ее административную работу проще. Между тем, на программисте GNOME налагает ответсвенность по разработке еще лучших программ, опирающихся на эти средства. Таким образом, и тот и другой находятся в полной гармонии друг с другом, поскольку их работа взаимосвязана.
Теперь давайте немного внимательнее рассмотрим функциональность Gnome. В действительности, GNOME -- программный уровень, расположенный между X Window System и Window Manager-ом. Итак, как упомянуто ранее, GNOME предоставляет огромный набор функций программирования GUI , который может быть использован в разработке программ для Linux. Но самая главная причина , по которой среда GNOME почти совершенно необходима для всех Linux/Unix разработчиков такова: GNOME обеспечивает разработчиков и программистов интегрированой средой, специально разработанной для построения open-source приложений с солгласованным графическим интерфейсом пользователя.
Проект GNOME стартовал в августе 1997 года. Среди отцов-основателей были следующие люди: Peter Mattis, Spencer Kimball, Richard Stallman, и Erik Troan и Ewing из Red Hat, Inc.
2. Архитектура GNOME
GNOME это черезвычайно мощная, к тому же гибкая архитектура, обеспечивающая необычайную функциональность. Основной инструментарий в GNOME называется GTK+(the GIMP toolkit). Первоначально он был написан для использования в GIMP(GNU Image Manipulation Program). Правильное понимание GTK+ совершенно необходимо для программирования в GNOME. GTK+ это объектно-ориентированный, кросс-платформенный и не зависящий от языка инструментарий, который в первую очередь используется для создания приложений независимых от собственно GNOME. Тогда возникает вопрос: Почему GTK+ был выбран в качестве инструментария для GNOME? Ответ прост: поддержка GTK+ включена в многие языки программирования включая C++, PERL, Python, ADA etc. Но полезно держать в голове, что и GNOME и GTK+ написаны на Cи, так что мы будем иметь здесь дело только с Си.
Другой вопрос, который может прийти в голову читателя: "Эй, а содержится что в этих штучках, названных "инструментарий"?" Инструментарии, такие как GTK+, Qt (KDE основан на Qt) - это набор виджетов. Ответ вызывает еще вопрос : "Что такое "виджеты"?"
Виджеты это объекты GUI такие как кнопки, меню, панели диалогов и др. или связанные с объектами функции. Это можно сравнить с Active Template Library (ATL 3.0) на платформе Microsoft, которая предоставляет разработчикам Component Object Model (COM) с готовой к использованию структурой для создания COM объектов и компонент (ActiveX EXE & ActiveX DLL).
3. GTK+ - Введение
Теперь давайте более внимательно рассмотрим некоторые особенности GTK+:
-
Набор библиотек, используемых GTK+: GLIB (GIMP Library) и GDK (GIMP Drawing Toolkit).
-
GLIB определяет типы данных и обеспечивает функциями для обработки ошибок и работы с памятью.
-
GDK - это платформно зависимый уровень который нахдится между API, присущим данной платформе, и GTK+.
-
Это еще не все. GNOME вносит дополнительную функциональность в GTK, добавляя отдельный слой специфических виджетов и библиотек.
-
Таким образом, GNOME основывается на функционально-полной, объектно-ориентированной, расширяемой архитектуре, базирующейся на виджетах.
-
Помимо возможностей GTK+, мы получаем дополнительные преимущества, связанные с внутренней реализацией системы CORBA, называемой ORBit, позволяющей программным объектам легко и эффективно взаимодействовать.
-
GLIB определяет свой собственный набор основных типов данных. Большинство из них эквивалентны стандартым типам данных в Си.
Тип данных GLIB |
Тип данных Си |
gchar |
char |
gshort |
short |
glong |
long |
gint |
int |
gboolean |
boolean |
gpointer |
void* |
8. Насущное требование для правильного понимания GTK - это концепция "Иерархии виджетов". Виджеты в GTK организованы иерерхически, так что функции, общие для набора виджетов, нужно реализовать лишь однажды.
Например, функция gtk_widget_show. Ее использование приводит к удалению повторяющегося кода, таким образом ведет к более быстрой и разработке программ лучшего качества. Новые виджеты получаются на основе высокоуровневых (по иерархии) виджетов, таким образом, только уникальные для этих виджетов функции нуждаются в написании программистом. Для примера внимательно рассмотрим данную иерархию виджетов:
GtkObject --> GtkWidget --> GtkContainer --> GtkBin --> GtkWindow --> GnomeApp
Итак, если вы смотрите внимательно, вы можете видеть, что виджет GnomeApp получен из виджета более высокого уровня GtkWindow, который сам в свою очередь был выведен из GtkBin и так далее. Если мы примем во внимание основные особенности языка программирования С++, это напомнит нам концепцию "наследования". Не так ли? Безусловно да. Наследование есть особеность "иерархии виджетов", которая соединяет в единое целое функиональность виджетов в GTK+.
Теперь давайте сделаем кратки обзор функций создания виджетов. Чтобы эти функции работыли корректно, нужно убедится, что все библиотеки GNOME и GTK+ правильно установлены. Другая важная вещь, которую нужно помнить перед компиляцией любого кода, это правильно установленые пути к месту нахождения библиотек.
Рассмотрим функцию создания виджета gnome_app_new(). Как показано, эта функция возвращает указатель на GtkWidget, который является общим виджетом. Это может быть продемонстрировано как:
GtkWidget *ghosh;
ghosh = gnome_app_new(………);
Пожалуста, примите во внимание -- это означает, что если мы хотим вызвать специфическую для GnomeApp функцию, такую как gnome_app_set_menus(), то мы должны использовать макрос, чтобы привести тип GtkWidget к GnomeApp; только так вохможно это сделать, поскольку GnomeApp создан на основе GtkWidget (см. иерархию выше).
4. Первая программа
Лучший путь изучения программирования в Linux -- это понимание внутренней работы ядра и попытки программирования самим. Так что давайте сейчас рассмотрим маленькую программу, чтобы лучше понять предмет, с которым мы имеем дело.
Загрузите Linux, и если вы в режиме командной строки, переключитесь в gnome, используя команду "switchdesk gnome", а затем введите команду "startx", чтобы загрузиться в режиме X Window System GUI. Оказавшись в среде GNOME, откройте GNOME Terminal, используя vi создайте файл с именем myapp.c и напечатайте в нем следующее:
/* A sample GNOME program
Created By: Subhasish Ghosh
Date: 8th August, 2001
*/
#include
int main(int argc, char *argv[ ])
{
GtkWidget *ghosh;
gnome_init("sample", "0.1", argc, argv);
ghosh = gnome_app_new("sample", "My Window");
gtk_widget_show(ghosh);
gtk_main();
return 0;
}
Теперь, чтобы скомпилировать программу myapp.c, введите команду(обратите внимание на обратные кавычки):
# gcc myapp.c -o myapp gnome-config --cflags --libs gnomeui
Обратите внимание, что GNOME приходит с shell скриптом названным gnome-config, который правильно устанавливает флаги компилятору для успешной компиляции. Однажды скомпилированную, программу можно запустить командой:
# ./myapp &
На экране появится пустое окно, которое вы можете перемещать, менять его размер, а так же закрывать. Теперь давайте внимательнее рассмотрим код. В начале мы ввели несколько строк комментария, описывающих программу - это создатель и дата создания. Хотя и не является необходимостью, это хорошая практика программирования включать такие строки в каждую программу. Затем мы включили заголовочный файл gnome.h, который берет на себя заботу о всех библиотечных функциях и определениях. Затем идет "ghosh" -- указатель на GtkWidget. Он будет указывать на наш новый оконный объект. Потом вызвана функция gnome_init. Она инициализирует библиотеки и использована для корректного управления сессией. ID переданный в функцию gnome_init является примером, текущий номер версии "0.1", и затем обычные аргументы командной строки функции main. Они необходимы для внутренней работы GNOME. Затем идет функция gnome_app_new(), которая при исполнении создает наше окно. Как показано в коде примера, она принимает два аргумента: "sample" и "My Window". "sample" это имя приложения, и "My Window" заголовок окна. Но, пожалуста учтите, что хотя имя функции gnome_app_new(), она НЕ создает никакого нового приложения или чего-нибудь такого. Она создает окно верхнего уровня (главное окно) и все. Следующая вызванная функция -- gtk_widget_show(), делает наше окно видимым. Затем идет gtk_main() -- очень важная функция, гарантирующая выполнение таких важных для GNOME процедур, как обработку событий и нажатий на клавиши внутренним функциям GNOME.
Итак -- это внутренняя работы нашей первой GNOME программы.
5. Сигналы & Callback-и
Теперь давайте более внимательно всмотримся в среду программирования GNOME: на "сигналы" и "callback-и", или функции обратного вызова . Что они такое и для чего используются? Зачем они на самом деле нам нужны? Каждый раз, когда движется мышь, нажимается кнопка, кнопка с фиксацией переводится в состояние вкл. или выкл., или происходят подобные вещи, приложению посылается сигнал. Сигнал может быть передан callback-функции. Итак, хотя и не всегда, но есть моменты, когда приложению нужно подключить выполнение определенных действий к этим событиям. В GNOME/GTK+ мы вызываем функцию, названную gtk_signal_connect, чтобы подключить сигналы к обрабатывающим их функциям.
функция gtk_signal_connect имеет следующие 4 параметра:
-
GtkObject *object -- Виджет, с которым ассоциируется callback.
-
const gchar *name -- Сигнал, который будет обработан.
-
GtkSignalFunc func -- Функция, которая будет вызвана, когда сигнал будет послан.
-
gpointer data -- Любые проризвольные данные, переданные обрабатывающей сигнал функции.
Нужно бы учесть, что различные типы виджетов эмитируют разные сигналы. Сигналы от кнопок следующие:
-
clicked -- По кнопке "кликнули" (нажали & отпустили).
-
pressed -- Кнопка нажата "мышью".
-
released -- Кнопка отпущена.
-
enter -- Курсор мыши вошел в предделы кнопки.
-
leave -- Мышь вышла за пределы кнопки.
Мы рассмотрим важную роль сигналов и callback-ов в приложениях, которые будем разарбатывать позднее.
6. Контейнеры
Следующим мы рассмотрим другой жизненно важный компонент программирования в GNOME: контейнеры. GTK+ очень широко использует контейнеры, потому что GTK+ --это реально"основанный на контейнерах" инструментарий. Это означает, что у нас всегда есть родительский контейнер, в который мы можем поместить другие наши виджеты. Окна -- это контейнеры с единственным виджетом. Важный момент, котоорый нужно держать в уме -- GTK+ использует невидимые "упаковочные панели", которые могут содержат множество виджетов для создания схемы их расположения в окне. Эти "упаковочные панели" бывают двух типов: горизонтальные и вертикальные, созданные работой функций gtk_hbox_new и gtk_vbox_new соответственно. Вскоре мы рассмотрим эти функции в действии, в приложении, которое создадим позднее. А сейчас, посмотрим на параметры этих двух функций:
-
homogeneous : тип --> gboolean : Заставляет все виджеты на панели занимать такую же площадь, какую занимает самый большой виджет.
-
spacing : тип --> gint : Определяет промежуток между соседними виджетами.
-
expand : тип --> gboolean : Позволяет упаковочной панели расшириться по всей оставшейся площади.
-
fill : тип --> gboolean : Позволяет определенному виджету расшириться по всей оставшейся площади.
-
padding : type --> gint : Определяет ширину рамки, окружающей виджет.
7. Кнопки
Следующим шагом, мы подошли к другому очень важному компоненту: кнопкам. GTK+ предоставляет 4 различных вида кнопок:
-
Простые кнопки --> Для выполнения действий по "клику".
-
Кнопки с фиксацией --> С определенными состояниями: Up/Down (Верх./Нижн.)
-
Флажки(check buttons) --> С двумя определенными состояниями: On/Off (Вкл./Выкл.)
-
Переключатели(radio buttons) --> Для выбора только одного флажка из группы.
Создание переключателей очень похоже на создание флажков, и все, что нам нужно сделать сверх того - это определить группу к которой относятся флажки. Переключатели получены из флажков, которые в свою очередь получены из кнопок с фиксацией, это означает, что мы имеет один и тот же набор функций для чтения и изменения их состоянияа, а также использовать the same old events. Пожалуйста имейте в виду: Для получения большей информации об определенных функциях см. документацию: GTK+ Reference Documentation, она доступна на: http://www.gtk.org/
8. Виджеты ввода
Для создания однострочных текстовых виджетов, которые в общем называны "виджеты ввода", мы используем функцию gtk_entry_new(). Эти виджеты в основном используются для ввода небольшого количества информации. Давайте рассмотрим программу, которая создает "Login Window" и при нажатии Enter показывает содержимое поля ввода пароля. Напечатайте следующий текст и запустите программу, как уже было объяснено выше.
/* Creating a Login GNOME-style using GTK+ Toolkit:
Created By: Subhasish Ghosh
Date: Wednesday, August 8, 2001
*/
#include
static void enter_pressed(GtkWidget *button, gpointer data)
{
GtkWidget *text_entry = data;
char *string = gtk_entry_get_text(GTK_ENTRY(text_entry));
g_print(string);
}
int main(int argc, char *argv[])
{
GtkWidget *app;
GtkWidget *text_entry;
GtkWidget *label;
GtkWidget *hbox; gchar *text;
gnome_init("example", "0.1", argc, argv);
app = gnome_app_new("example", "entry widget");
gtk_container_border_width(GTK_CONTAINER(app), 5);
hbox = gtk_hbox_new(FALSE, 0);
/* we now create a Label: */
label = gtk_label_new("Password: ");
gtk_misc_set_alignment(GTK_MISC(label), 0, 1.0);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
text_entry = gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(text_entry), FALSE);
gtk_box_pack_start(GTK_BOX(hbox), text_entry, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(app), "delete_event", GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_signal_connect(GTK_OBJECT(text_entry), "activate", GTK_SIGNAL_FUNC(enter_pressed), text_entry);
gnome_app_set_contents(GNOME_APP(app), hbox);
gtk_widget_show_all(app);
gtk_main( );
return 0;
}
Когда запущена эта программа, на экране появляется окно с полем для ввода пароля. Напечатайте там любой текст (предполагается, что это пароль), нажмите Enter и посмотрите, что произойдет.
9. Списки и раскрывающиеся списки.
Списки и раскрывающиеся списки играют здесь ту же роль, что и на платформе Microsoft. Виджеты списков содержат список строк, позволяющие пользователю сделать выбор из одного или более элементов списка; concerned the widget is so configured. Раскрывающиеся списки -- это виджеты для ввода информации с добавленным выпадающим меню, позволяющим пользователю также сделать выбор из уже имеющихся вариантов.
10. Меню & Панели инструментов
Различные виджеты, по которым мы прошлись до этого момента являются простыми виджетами, которые не обеспечивают какой-либо экстраординарной функциональности. Теперь мы рассмотрим некоторые специальные библиотеки программирования GNOME, предлагающие более сложные виджеты с расширенными возможностями.
Отвлечемся на секунду, кое-кто может спросить: "Эй, мы прекрасно работаем с обычным кодом и всем тем, что вы обсудили ранее. Зачем использовать эти так называемые "специальные библиотеки программирования GNOME"? Являются ли они на самом деле полезными? Или вы просто включаете их описание здесь, чтобы сделать статью немного длиннее?"
Хорошо, причина для рассмотрения этих библиотек есть. Хотя используя простой код GTK+, можно сделать почти все, что обычно делается с использованием специальных библиотек, использование этого простого GTK+ кода часто приводит к повторению, неэффективным блокам кода и к другим подобным вещам, и делает программу раздутой. Чтобы избежать этого, мы используем специальные библиотеки, которые обеспечивают широчайшую функциональность и требуют гораздо меньше программирования.
Итак, давайте поговорим о "Меню" и "панелях инструментов". GNOME позволяет нам создавать меню и панели инструментов, которые могут быть присоединены к окну (находиться в самом окне), так и отсоединены (быть вне его пределов). Сначала вы заполняете структуру необходимой информацией, затем вызываете gnome_app_create_menus или gnome_app_create_toolbar.
Элементы меню и панелей инструментов имеют каждый свои свойства, определенные в описании. Вот некоторые из них: тип, указатель на callback и т.д. В большинстве случаев описания пунктов меню очень просты и мы можем просто использовать один из набора макросов предоставляемых GNOME, чтобы он создал структуру для нас. Итак, давайте рассмотрим несколько наиболее часто используемых высокоуровневых макросов.
Пожалуйста учтите: Это те макросы, которые создают top-level меню когда им передан массив, содержащий все или несколько следующих GnomeUIInfo структур.
Menu |
Macro |
File |
GNOMEUIINFO_MENU_FILE_TREE(tree) |
Edit |
GNOMEUIINFO_MENU_EDIT_TREE(tree) |
View |
GNOMEUIINFO_MENU_VIEW_TREE(tree) |
Settings |
GNOMEUIINFO_MENU_SETTINGS_TREE(tree) |
Windows |
GNOMEUIINFO_MENU_WINDOWS_TREE(tree) |
Help |
GNOMEUIINFO_MENU_HELP_TREE(tree) |
Game |
GNOMEUIINFO_MENU_GAME_TREE(tree) |
Внутри меню верхнего уровня создано больше тридцати макросов для создания общих пунктов меню. Макрос ассоциирует маленькие картинки (pixmaps) и горячие клавиши с каждым пунктом меню. Когда пункт меню выбран, происходит вызов callback-функции для обработки этого события и ей в качестве параметра передается указатель на данные.
Давайте рассмотрим некоторые общие пункты меню и соответствующие им макросы.
File -->>
New --> GNOMEUIINFO_MENU_NEW_ITEM (label, hint, cb, data)
Open --> GNOMEUIINFO_MENU_OPEN_ITEM (cb, data)
Save --> GNOMEUIINFO_MENU_SAVE_ITEM (cb, data)
Print --> GNOMEUIINFO_MENU_PRINT_ITEM (cb, data)
Exit --> GNOMEUIINFO_MENU_EXIT_ITEM (cb, data)
Edit -->>
Cut --> GNOMEUIINFO_MENU_CUT_ITEM (cb, data)
Copy --> GNOMEUIINFO_MENU_COPY_ITEM (cb, data)
Paste --> GNOMEUIINFO_MENU_PASTE_ITEM (cb, data)
Settings -->>
Preferences --> GNOMEUIINFO_MENU_PREFERENCES_ITEM (cb, data)
Help -->>
About --> GNOMEUIINFO_MENU_ABOUT_ITEM (cb, data)
Подобно меню, панели инструментов созаются с использованием макроса GNOMEUIINFO_ITEM_STOCK (label, tooltip, callback, stock_id). Здесь "stock_id" - это идентифкатор предопределенной иконки, изображение которой мы хотим видеть на соответствующей кнопке.
Давайте посмотрим на этот пример и увидим, как описания и макросы работаю в реальности.
#include
static void callback (GtkWidget *button, gpointer data)
{
g_print("Item Selected");
}
GnomeUIInfo file_menu[ ] = {
GNOMEUIINFO_ITEM_NONE ("A menu item", "This is the Status bar info", callback),
GNOMEUIINFO_MENU_EXIT_ITEM (gtk_main_quit, NULL),
GNOMEUIINFO_END
};
GnomeUIInfo menubar[ ] = {
GNOMEUIINFO_MENU_FILE_TREE (file_menu),
GNOMEUIINFO_END
};
GnomeUIInfo toolbar[ ] = {
GNOMEUIINFO_ITEM_STOCK ("Print", "This is another tooltip", callback, GNOME_STOCK_PIXMAP_PRINT),
GNOMEUIINFO_ ITEM_STOCK ("Exit", "Exit the application", gtk_main_quit, GNOME_STOCK_PIXMAP_EXIT),
GNOMEUIINFO_END
};
int main (int argc, char *argv[ ])
{
GtkWidget *app;
gnome_init ("example", "0.1", argc, argv);
app = gnome_app_new ("example", "A Sample Toolbar and Menu");
gnome_app_create_menus (GNOME_APP (app), menubar);
gnome_app_create_toolbar (GNOME_APP (app), toolbar);
gtk_widget_show_all (app);
gtk_main();
return 0;
}
Эта программа создает маленькое окно с меню и инструментальной панелью внутри. Вы можете выбирать пункты меню, "вытаскивать" меню и панели инструментов из окна, перемещать по экрану и возвращать обратно.
11. Диалоги
Давайте теперь рассмотрим виджет, который показывает пользователю текстовую информацию в среде GNOME. Да, мы имеем в виду панель диалога. Когда нам нужно создать панель диалога, мы вызываем функцию gnome_message_box_new и передаем ей текст сообщения, который мы хотим на ней видеть, также описываем тип диалога, и требуемые кнопки. Все это заносится в список завершающийся NULL-ем. Потом мы увязываем сигнал "clicked" диалогового виджета с обрабатывающей функцией, которой передается номер нажатой кнопки в качестве целого числа. И наконец, мы вызываем функцию gtk_widget_show для вывода на экран немодального диалога.
Давайте посмотрим на часть кода программы, который создает простой диалог с вопросом, добавляет в него три кнопки и responds to the user's code.
static void messagebox_clicked(GnomeDialog *dlg, gint button, gpointer data)
{
switch (button)
{
case 1: /* user pressed apply */
return;
case 0: /* user pressed ok */
case 2: /* user pressed close */
gnome_dialog_close(dlg);
}
}
GtkWidget *dlg;
dlg = gnome_message_box_new("Hi, pal, how are you doing??? I am fine!",
GNOME_MESSAGE_BOX_QUESTION,
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_APPLY,
GNOME_STOCK_BUTTON_CLOSE,
NULL);
gtk_signal_connect (GTK_OBJECT(dlg), "clicked", GTK_SIGNAL_FUNC(messagebox_clicked), NULL);
gtk_widget_show (dlg);
12. Заключение & Ссылки для дальнейшего изучения
Подведем итог нажему путешествию в мире программирования с использованием инструментария GTK+.
Пожалуйста учтите: программирование в GNOME не очень трудное. Если у вас есть немного способностей, то вы легко все поймете. После этой статьи осталось изучить еще много, но если подойти к этому старательно, то одолеть можно.
Для полущения большей информации о предмете данной статьи и более детального рассмотрения проверьте следующие ссылки:
http://www.linuxheadquarters.com/howto/programming/gtk_examples/index.shtml
http://www.ibiblio.org/pub/Linux/docs/HOWTO/mini/other-formats/html_single/Programming-Languages.html
http://linuxheadquarters.com/howto/programming/gtk_examples/window/window.shtml
http://developer.gnome.org/doc/GGAD/ggad.html
http://wolfpack.twu.net/docs/gtkdnd/index.html
Massagery.ru. Современное массажное кресло.