Новости · Пользователю · Переводчику · Разработчику · Ресурсы

Программирование на Java c использованием GTK+

Уровень читателя: опытный, знание Java
25 февраля 2006, Сергей Безденежных (sib-mail@mtu-net.ru)


В этой статье вы узнаете о средствах, необходимых при создании приложений на языке Java для Gtk+ и Gnome. На простом примере познакомитесь с основами использования инструментария Gtk+ в программах на языке Java. Затем на другом примере увидите, как из программы на Java использовать файлы описания графического интерфейса, созданные с помощью дизайнера интерфейсов Glade.


С каждым годом популярность рабочего окружения Gnome растет, и все больше и больше разработчиков задумываются о совместимости своих приложений с этой средой. В то же время увеличивается популярность языка Java: объектно-ориентированные свойства, сборка мусора, межплатформенные возможности, библиотеки классов сделали этот язык идеальным для решения определенного круга задач. Естественно, что некоторые разработчики хотели бы использовать язык Java при разработке своих приложений для среды GNOME. Чтобы предоставить разработчикам такую возможность, сообществом программистов GNOME был организован проект Java-GNOME, в рамках которого был разработан ряд привязок к основным библиотекам GTK+ и GNOME.

Необходимое ПО

Для программирования в Java с использованием инструментария GTK+ нам понадобятся, как минимум, три вещи:

В качестве компилятора можно использовать как JRE от Sun, так и открытые GCJ или Kaffe. На сайте Java-GNOME ни одному из них явного предпочтения не отдают. Но надо обратить внимание на GCJ – он единственный позволяет создавать код, который в последующим может быть запущен без Java-машины, кроме этого, он поставляется с большинством современных дистрибутивов Linux. Помимо компилятора дополнительно понадобится Java-машина, здесь так же явных предпочтений нет, поэтому все зависит от вашего выбора. Приведенные в этой статье примеры были скомпилированы с помощью gcj и запускались с помощью открытой виртуальной машины из состава GCC 4.0.1 на системе Fedora Core 4 Linux x86–64.
Как упоминалось ранее, Java-GNOME – это набор привязок для различных библиотек GTK+ и Gnome. Некоторые из них официально создаются в рамках проекта Java-GNOME, однако существует и масса других неофициальных привязок. К официальным привязкам относят следующие четыре пакета:

Дополнительные пакеты специально нигде не учитываются, тем не менее, отметим наиболее известные из них:

По адресу http://java-gnome.sourceforge.net/cgi-bin/bin/view/Main/GetJavaGnome можно подробно узнать о том, как получить и установить пакеты java-gnome для Windows, и разных дистрибутивов Linux.
Конечно, простые программы можно создавать в любимом текстовом редакторе, например, в gedit. Однако гораздо удобнее, когда в редактор встроены средства отладки и подсветки синтаксиса. Интегрированные среды разработки предоставляют эти и ещё множество удобных и полезных функций. Разработку с Java-Gnome поддерживают, как минимум, две популярных среды разработки: Eclipse и NetBeans. Обе из них являются открытыми и доступны для загрузки.

Простой пример программы на Java

Познакомившись с пакетами из проекта Java-GNOME, попробуем разобраться с кодом написанной на java несложной программы, использующей графический инструментарий GTK+. В листинге 1 представлен код программы first.
Листинг 1. Приложение first.

После запуска эта программа создает окно размером 200 на 100 пикселей с единственной кнопкой «Информация» посередине. Окно изображено на рисунке 1. После нажатия на эту кнопку появляется модальный диалог «Информация» с надписью «Привет мир!».
Рисунок 1 – окна программы first.
 (16 Кб)
Перед тем, как начать разбор кода программы first, для тех, кто давно не программировал на Java, напомню два важных момента: в любой Java-программе должен быть реализован хотя бы один класс, выполнение программы, начинается с вызова статического метода main.
В первой строчке метода main(), нашего единственного класса first, происходит вызов метода init() из пакета gtk. Этот вызов инициализирует наше приложение и устанавливает некоторые переменные окружения среды GNOME. Параметром этого метода нужно указать аргументы командной строки args, передаваемые методу main() из командной строки, Gnome обработает и учтет эти аргументы. Обратите внимание, что вызов этого метода для приложений GTK обязателен, причем он должен быть осуществлен до вызова любых других методов GTK+. Если вы пропустите метод init(), ваше приложение скомпилируется, однако при запуске возникнет множество ошибок неизвестной природы.
Если вы ранее программировали с GTK+ на языке С, то, наверное, уже заметили, что метод main() выполняет ту же работу, что и функция gtk_init() на С. Да, это так, более того, создатели привязок Java-GNOME постарались, насколько это возможно, приблизить синтаксис выражений на С к выражениям на Java, дабы максимально унифицировать использование инструментария.
В следующей строке мы создаем новый экземпляр нашего класса first. Напомню, что создание нового экземпляра класса, начинается с вызова конструктора, который имеет то же название что и класс. Проще говоря, далее будет вызван метод first(), в котором содержится код создания окна. Но зачем нам вызывать какие-то конструкторы для создания окна, почему бы просто не включить этот код в метод main()? Теоретически, так можно сделать, и окно будет нормально создано, сложности начнутся, когда мы решим использовать в обработчиках событий объекты, созданные в методе main().
Для того чтобы объекты были видны в разных методах класса, нам придется объявить их не внутри метода main(), а как поля класса first. Поскольку метод main() является статическим, компилятор не позволит нам обратиться к не статическому полю внутри этого метода. Чтобы решить эту проблему, требуется сделать эти поля статическими, что для элементов интерфейса просто не допустимо. Выходом из этой ситуации является создание объектов в нестатическом методе, что мы и сделали, поместив их в конструктор класса.
Последней строчкой в методе main() нашей программы является вызов метода main() пакета gtk. Это так называемый вход в главный цикл. Обработка событий любого GTK+ приложения начинается именно с этого вызова, поэтому, как и метод init(), он обязательно должен присутствовать в программе. Если вы случайно забудете его сделать, то не увидите сообщений об ошибках, запуска программы попросту не произойдет.
Как было упомянуто выше, перед тем как войти в главный цикл, создается экземпляр класса first и, соответственно, вызывается его конструктор – метод first(). Рассмотрим подробнее, что происходит в этом методе.
Первые строчки выглядят так:

Прежде всего, здесь создаются объекты виджетов, а точнее двух виджетов: окна win и кнопки button, ранее объявленных полями нашего класса first. Конструктор окна, в качестве параметра принимает одно из двух значений WindowType.TOPLEVEL и WindowType.POPUP. Второе относится к всплывающим окнам, поэтому мы используем значение TOPLEVEL.
Конструктору кнопки мы передали значение GtkStockItem.DIALOG_INFO – это готовая кнопка с надписью «Информация» и изображением лампочки. Есть еще множество других кнопок, узнать о них можно в документации по API javadoc-libgtk. Конечно же, у кнопки есть конструктор, где можно самому задать надпись и/или рисунок. Однако если мы используем готовую кнопку, то надпись на ней будет автоматически переведена на язык той системы, на которой запущена наша программа, и картинка будет следовать стилю выбранной в системе теме иконок.
Третьей инструкцией мы помещаем кнопку внутрь окна, при этом в отличие от ОС Windows, где каждому элементу интерфейса нужно задавать абсолютные координаты, в GTK+ размеры и положение виджетов вычисляются автоматически. В нашем случае кнопка займет все доступное пространство, то есть все окно. Существуют разные методы размещения виджетов, кроме того, существуют специальные виджеты, не рисующие ничего на экране, и предназначенные только для размещения в них других виджетов. Подробнее узнать о специальных виджетах и методах размещения можно в документации по GTK+.
Следующие две большие по объему инструкции создают два обработчика событий:

Этот способ обработки событий знаком для Java-программистов. Через специальный интерфейс к объекту добавляется слушатель, в котором реализуются методы обработки событий.
К нашему окну мы подключаем обработчик события выхода (т.е. нажатия на кнопку закрытия окна), в нем нам нужно выйти из главного цикла, иначе даже после удаления окна с экрана, память не будет освобождена. Для этого в интерфейсе LifeCycleListener нам придется реализовать 2 метода: lifeCycleEvent() и lifeCycleQuery(). Первый – для всех событий связанных с жизненным циклом окна, второй – для тех, которые возвращают какое-либо значение, т.е. для DELETE и DESTROY. В метод lifeCycleQuery(), мы и добавим вызов метода mainQuit() пакета gtk, кроме того, этот метод должен вернуть логическое значение. Если lifeCycleQuery() возвратит false, GTK+ удалит виджет и освободит память, иначе процесс завершения программы будет приостановлен.
К кнопке мы подключаем обработчик с методом buttonEvent(). В отношении кнопки, как известно, возникает несколько событий: нажатие, ее отпускание, вход указателя мыши в прямоугольник кнопки, его выход и т.д. Из них нам нужно обработать только нажатие. Для этого мы проверяем тип пришедшего события event, и если он соответствует, ButtonEvent.Type.PRESS начинаем обработку. В коде обработчика создается модальный диалог предопределенного типа MessageType.INFO (информационный диалог) с одной кнопкой «ОК» и надписью «Привет мир!». Дальше этот диалог запускается, поскольку это модальный диалог, выполнение программы будет приостановлено вплоть до его завершения, поэтому следующей инструкцией мы можем свободно удалить этот диалог из памяти.
Надо отметить, что, так как обработчик подключается через интерфейс, нам никто не запрещает создать собственный класс, реализующий этот интерфейс. Например, обработку нажатия на кнопку можно было произвести следующим образом:
1. Создать класс, реализующий интерфейс ButtonListener и обработчик событий:

2. Добавить слушателя следующим образом:

После регистрации всех обработчиков событий, мы устанавливаем размеры окна:

и, в конце концов, показываем наше окно и все его виджеты на экране:

Подведем краткие итоги. Надо запомнить, что в большинстве программ GTK+, написанных на Java, должны присутствовать следующие вещи:

1. Вызов метода gtk.init() перед тем, как будут сделаны любые другие вызовы GTK+;
2. Отдельный класс, в конструкторе которого создаются и размещаются виджеты;
3. Вход в главный цикл gtk.main();
4. Выход из главного цикла gtk.mainQuit().

Компиляция и запуск

Чтобы скомпилировать программу, использующую java-gnome, в путь поиска классов надо включить jar-архивы привязок. В зависимости от установленной у вас версии java-gnome они будут иметь названия вида gtk2.X.jar, gnome2.X.jar, glade2.X.jar и gconf2.X.jar. Обычно они находятся в каталоге /usr/share/java, так что команда компиляции будет иметь вид:

Соответственно запустить получившийся класс first.class можно командой:

Использование Glade в Java

Рассмотренный выше пример java-прогрммы, использующий GTK+, не претендует на роль полезного приложения, поэтому графический интерфейс его достаточно скуден. Однако в настоящих приложениях нас вряд ли устроит окно с одной кнопкой посередине. Вручную же описывать создание каждого виджета и его свойства в большом проекте достаточно трудоемко. Кроме того, многие программисты просто привыкли к различным средствам быстрой разработки программ, где создание будущей формы происходит визуально – перетащил нужные элементы, расположил их, задал их свойства – и готово.
Визуально создавать интерфейс так быстро и удобно, что программисты GTK+ сделали свое средство быстрого создания графического интерфейса. Называется это средство Glade, в него входит несколько библиотек для подключения к программе файлов с формами, описанными в формате XML и программа «Дизайнер интерфейсов». В этом дизайнере интерфейсов можно привычным образом перетащить и расположить нужные виджеты, задать их свойства и подключить к ним сигналы. После того, как форма готова, она сохраняется в специальном формате XML в фале с расширением .glade.
В листинге 2 представлен код программы, использующий форму, предварительно созданную в дизайнере интерфейса Glade. Код формы можно найти в архиве с примерами.
Листинг 2. Код программы, использующей Glade.

Скомпилировав и запустив этот код, мы увидим окно, изображенное на рисунке 2.
Рисунок 2 – окно программы, использующей glade.
 (9 Кб)
Посмотрите на рисунок, тут у нас и меню, и строка состояния, и виджет дерева с линейками прокрутки – все это без единой строчки кода. Собственно в коде программы описаны только обработчики событий, а вся работа по созданию виджетов возложена на glade.
Использование glade в нашей второй программе начинается с создания объекта LibGlade. Его конструктор в качестве параметра ожидает имя файла .glade с описанием формы:

Чтобы использовать объекты виджетов, созданных в Glade, нужно их предварительно подгрузить, для чего объявляется переменная подходящего типа и вызывается метод getWidget объекта LibGlade. В нашем случае, для того чтобы правильно завершить программу, мы подгружаем объект окна:

Желаемый виджет получают по имени, заданному при проектировании формы, в нашем случае это “window”, при этом метод getWidget() возвращает объект типа Widget, поэтому дополнительно нужно выполнить приведение типов, для нас к типу Window. С полученным объектом уже можно работать, в том числе и цеплять к нему обработчики событий, как сделано в нашей программе.
При всем этом, для обработки событий намного удобней воспользоваться функциями Glade. Дело в том, что во время проектирования формы можно сразу указать имена обработчиков событий для виджетов. Таким вот способом в нашем примере выполнена обработка нажатия элемента меню «Выход». При проектировании формы в «Дизайнере интерфейсов» для объекта меню on_exit на событие Activate был определен обработчик on_exit_activate(). Теперь чтобы выполнить обработку сигнала нажатия меню, достаточно создать дополнительный метод с таким же названием.
Обратите внимание на то, что такой подход избавляет нас от необходимости подгрузки объекта меню. Кроме того, разделение интерфейса и кода программы позволяет сосредоточиться на логике программы. В общем, используйте Glade в своих проектах.

Приложение

Исходные коды примеров (examples.zip, 3Кб)

Ссылки

1. Посетите сайт проекта Java-GNOME
2. Прочитайте статьи из цикла «Основы GTK+»;
3. Посетите сайт GTK+, чтобы получить больше информации об инструментарии;
4. Каждому разработчику Java-GNOME понадобиться документация по API.

 
Много файлов (3). [Показать файлы/форму]
Комментариев нет. [Показать комментарии/форму]