Содержание


Язык программирования go

Часть 4. Создание GUI-приложений

Comments

Серия контента:

Этот контент является частью # из серии # статей: Язык программирования go

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Язык программирования go

Следите за выходом новых статей этой серии.

Библиотека Gtk+ (GIMP Toolkit) – это набор виджетов для создания пользовательского интерфейса. Это зрелый проект с большой коллекцией GUI-элементов, что позволяет создавать высокофункциональные и дружественные к пользователю приложения. Хотя библиотека gtk изначально была написана на языке Си, однако имеется большое количество версий этой библиотеки, адаптированных для других языков. В данной статье будет рассматриваться использование библиотеки gtk в языке go.

Существующая библиотека go-gtk не обладает всеми возможностями gtk, но в ней присутствуют основные элементы GUI (такие как кнопки, списки, меню и т.д.). Также библиотека go-gtk не является 100% go-библиотекой, так как в ней используются вызовы к исходной библиотеке gtk.

Установка

Перед установкой библиотеки go-gtk желательно обновить используемую версию языка go, как показано ниже:

  hg clone https://go.googlecode.com/hg/ go
  cd go/src 
  ./all.bash

При использовании устаревшей версии go для сборки библиотеки go-gtk могут возникнуть ошибки, связанные с несоответствием используемых версий языка и библиотеки:

  glib.go:282[_obj/glib.cgo1.go:285]: reflect.NewValue(value).
  UnsafeAddr undefined (type reflect.Value has no field or method UnsafeAddr)

Также потребуются dev-файлы библиотеки gtk и сама библиотека. В большинстве дистрибутивов Linux библиотека gtk устанавливается по умолчанию, а файлы для разработки потребуется установить отдельно. Для этого необходимо добавить в систему пакеты libgtk2.0-dev и gtksourceview-2.0-dev, хотя в различных дистрибутивах Linux они могут называться и по-другому. Если в процессе сборки библиотеки go-gtk возникнут ошибки из-за отсутствия заголовочных файлов, то их можно будет устранить путем установки отсутствующих пакетов.

Библиотеку go-gtk можно загрузить по данному адресу` [https://github.com/mattn/go-gtk] или получить с помощью данной команды:

  git clone https://github.com/mattn/go-gtk.git

После этого необходимо перейти в каталог, куда была загружена библиотека, и выполнить следующую команду:

  make install

В результате библиотека go-gtk будет собрана и установлена в нужное место. Проблемы могут возникнуть, если не установлена переменная окружения GOROOT или в переменной PATH отсутствует путь к исполняемым файлам go. В этом случае перед запуском make потребуется выполнить следующие команды:

  export GOROOT=~/go
  export PATH=$PATH:~/go/bin

Использование возможностей go-gtk

В листинге 1 приведен код демонстрационного приложения, который будет подробно проанализирован ниже. Представленного примера должно быть достаточно, чтобы познакомиться с принципами работы библиотеки go-gtk. Приложение не решает какой-либо конкретной бизнес-задачи, а лишь демонстрирует наиболее популярные элементы пользовательского интерфейса. Вся его функциональность заключается в выводе приветственного сообщения при нажатии на кнопку.

Листинг 1. Пример приложения, использующего библиотеку go-gtk
package main

import (
	"gtk"
)

func main() {
	gtk.Init(nil)
	window := gtk.Window(gtk.GTK_WINDOW_TOPLEVEL)
	window.SetTitle("gtk-go example")
	window.Connect("destroy", func(ctx *gtk.CallbackContext) {
		println(ctx.Data().(string))
		gtk.MainQuit()
	}, "data for callback function")
	
	vbox := gtk.VBox(false, 1)

	frame := gtk.Frame("Demo")
	framebox := gtk.VBox(false, 1)
	frame.Add(framebox)

	entry := gtk.Entry()
	entry.SetText("<Name>")
	framebox.Add(entry)

	buttons := gtk.HBox(false, 1)

	button := gtk.ButtonWithLabel("Hello me")
	button.Clicked(func() {
		print("button clicked: ", button.GetLabel(), "\n")
		messagedialog := gtk.MessageDialog(
			button.GetTopLevelAsWindow(),
			gtk.GTK_DIALOG_MODAL,
			gtk.GTK_MESSAGE_INFO,
			gtk.GTK_BUTTONS_OK,
			"Hello, " + entry.GetText())
		messagedialog.Response(func() {

			
			messagedialog.Destroy()
		})
		messagedialog.Run()
	})
	buttons.Add(button)

	framebox.Add(buttons)

	menubar := gtk.MenuBar()
	vbox.PackStart(menubar, false, false, 0)


	cascademenu := gtk.MenuItemWithMnemonic("_File")
	menubar.Append(cascademenu)
	submenu := gtk.Menu()
	cascademenu.SetSubmenu(submenu)

	menuitem := gtk.MenuItemWithMnemonic("E_xit")
	menuitem.Connect("activate", func() {
		gtk.MainQuit()
	})
	submenu.Append(menuitem)

	
	cascademenu = gtk.MenuItemWithMnemonic("_Help")
	menubar.Append(cascademenu)
	submenu = gtk.Menu()
	cascademenu.SetSubmenu(submenu)

	menuitem = gtk.MenuItemWithMnemonic("_About")
	menuitem.Connect("activate", func() {
		dialog := gtk.AboutDialog()
		dialog.SetName("go-gtk library")
		dialog.SetProgramName("helloworlder 1.0")
		
		dialog.Run()
		dialog.Destroy()
	})
	submenu.Append(menuitem)
	

	vbox.Add(frame)

	window.Add(vbox)
	window.SetSizeRequest(400, 100)
	window.ShowAll()
	gtk.Main()
}

В листинге 2 представлен makefile для данного приложения.

Листинг 2. Makefile для сборки приложения
include $(GOROOT)/src/Make.inc
TARG=helloworlder
GOFILES=helloworlder.go
include $(GOROOT)/src/Make.cmd

Работа с gtk в языке go ничем, кроме синтаксиса, не будет отличаться от использования gtk в языке Си. Так, приложение начинается с вызова gtk.Init(nil) в методе main() для инициализации среды исполнения gtk. На этом этапе инициализируется библиотека gtk, поэтому эта функция должна вызываться самой первой, до использования любых других функций gtk. После этого создается окно и указывается его заголовок.

На следующей строке демонстрируется работа с событиями и использование callback-функций. В листинге 3 приведен вызов функции Connect.

Листинг 3. Использование функции Connect
window.Connect("destroy", func(ctx *gtk.CallbackContext) {
    println(ctx.Data().(string))
    gtk.MainQuit()
}, "data for callback function")

В эту функцию передается строка destroy, соответствующая событию «закрытие окна». Для каждого типа элементов имеется набор событий, на которые он может реагировать, например, для кнопки можно установить вызов функции для событий button-press-event и enter. Функция, которая будет вызвана при наступлении события, задается следующим параметром, а за ней следует набор передаваемых ей аргументов. В листинге 4 представлен исходный код функции Connect.

Листинг 4. Исходный код функции Connect
  func (v *GtkWidget) Connect(s string, f CallbackFunc, datas ...interface{}) {
         var data interface{}
         if len(datas) &gt; 0 {
                data = datas[0]
         }
         ctx := &amp;CallbackContext{f, nil, reflect.NewValue(v), reflect.NewValue(data)}
         ptr := C.CString(s)
         defer C.free_string(ptr)
         ctx.cbi = unsafe.Pointer(C._gtk_signal_connect
  (unsafe.Pointer(v.Widget), C.to_gcharptr(ptr), C.int(callback_contexts.Len())))
         callback_contexts.Push(ctx)
  }

Как видно, в листинге 4 активно используются вызовы Си-функций исходной библиотеки gtk. Остальные функции библиотеки go-gtk работают по сходному сценарию, а сама библиотека go-gtk, по сути, является адаптером для библиотеки gtk.

Метод Connect привязывает функцию к определенному событию в приложении. Пользователям gtk вызов C._gtk_signal_connect() покажется знакомым, так как это действительно вызов «родной» функции gtk_signal_connect(), в котором и выполняется вся работа.

Листинг 5. Создание контейнеров для GUI-элементов
 vbox := gtk.VBox(false, 1)
         frame := gtk.Frame("Demo")
         framebox := gtk.VBox(false, 1)
         frame.Add(framebox)

В листинге 5 создаются виджеты-контейнеры. GUI-компонент, создаваемый при вызове gtk.VBox(), является аналогом виджета GtkVBox из библиотеки gtk, который создается функцией gtk_vbox_new(). Метод Add позволяет «встраивать» один элемент в другой. В листинге 6 создаются конкретные элементы управления.

Листинг 6. Создание элементов управления
 entry := gtk.Entry() //создание поля ввода
         framebox.Add(entry) //добавление поля ввода в контейнер
         button := gtk.ButtonWithLabel("Hello me") // создание кнопки

В листинге 7 представлен код метода для обработки события button clicked (нажатие на кнопку).

Листинг 7. Установка вызова callback-функции для обработки нажатия кнопки
 button.Clicked(func() {
                print("button clicked: ", button.GetLabel(), "\n")
                messagedialog := gtk.MessageDialog(
                       button.GetTopLevelAsWindow(),
                       gtk.GTK_DIALOG_MODAL,
                       gtk.GTK_MESSAGE_INFO,
                       gtk.GTK_BUTTONS_OK,
                       "Hello, " + entry.GetText())
                messagedialog.Response(func() {
                       messagedialog.Destroy()
                })
                messagedialog.Run()
         })

Здесь также используется механизм обратных вызовов. В метод Clicked() передается callback-функция, в которой происходит создание диалогового окна. Подробное описание этой функции можно найти в документации gtk. При вызове функции Response() объекта messagedialog ей передается другая callback-функция, которая отвечает за закрытие диалогового окна. Таким образом, закрытие окна привязывается к событию «нажатие на кнопку». На последней строке происходит вызов messagedialog.Run() для отображения окна на экране.

В листинге 8 приведен фрагмент исходного кода, отвечающий за создание и наполнение главного меню приложения. Подчеркнутая буква в названии выпадающего меню соответствует клавише быстрого доступа (в данном случае Alt+F для меню File).

Листинг 8. Создание меню приложения.
  //создание главного меню приложения
         menubar := gtk.MenuBar()    
  vbox.PackStart(menubar, false, false, 0)
       //создание выпадающего меню 
         cascademenu := gtk.MenuItemWithMnemonic("_File")
         menubar.Append(cascademenu)
         submenu := gtk.Menu()
         cascademenu.SetSubmenu(submenu)
       //создания пункта меню
         menuitem := gtk.MenuItemWithMnemonic("E_xit")
         //привязка callback-функции для данного пункта меню
         menuitem.Connect("activate", func() {
                gtk.MainQuit()
         })
         submenu.Append(menuitem)

Аналогичным способом создаются и остальные элементы меню, которые затем помещаются в соответствующие контейнеры.

Завершается приложение добавлением главного контейнера в окно приложения и установкой размеров этого окна. Вызов gtk.Main() приведет к выводу окна на экран и отображению всех добавленных в него GUI-компонентов.

Заключение

В данной статье был продемонстрирован пример работы с базовыми элементами пользовательского интерфейса. Хотя библиотека go-gtk не обладает всеми возможностями gtk, тем не менее, даже имеющийся набор позволяет создавать достаточно функциональные GUI-приложения. К сожалению, справочная информация для библиотеки go-gtk пока не доступна, но нужную информацию можно найти в документации к библиотеке gtk, так как большая часть функциональности go-gtk просто выполняет вызовы к базовой библиотеке. Также информацию можно получить из исходного кода библиотеки go-gtk.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=696876
ArticleTitle=Язык программирования go: Часть 4. Создание GUI-приложений
publish-date=07052011