Дата и время публикации :
Назначение и использование
1. Назначение
1.1 GObject интроспекция
Для упрощения создания, развертывания и выполнения прикладных приложений в графическом окружении рабочего стола Gnome существует возможность написания скриптов на языке программирования Python с использованием языковых привязок, реализуемых с помощью интроспекции GObject
В свою очередь, интроспекцией GObject (GObject introspection, GI) является программная прослойка для связки языков более высокого уровня программирования с библиотеками GObject, написанными на языке программирования С и сканируемых во время компиляции, генерации файлов с метаданными в дополнении к фактически существующей библиотеки на С
Как показано на рисунке 1.1 привязывание языка высокого уровня производится автоматически обеспечивая вызов внутри библиотеки С
Рисунок 1.1
Таким образом, как следует из рисунка 1.1, проект GI состоит из :
- формата XML, называемым GIR, содержащий интроспектируемую информацию в перевариваемом машинным формате;
- пакета Python, что создает и разбирает формат GIR;
- сканера, генерирующего формат GIR из исходника и заголовков на С;
- библиотеки typelib, похожей на xpcom/msole, для того чтобы сохранить информацию на диск в бинарном формате;
- компилятора, компилирующего библиотеку typelib из формата xml (и обратно);
- библиотеки C , чтобы читать typelib, и libgirepository, которая обеспечивает доступ к данным typelib и взаимодействует с соответствующими базовыми библиотеками GObject
1.2 Языковая связка PyGObject
Для реализации языка программирования Python используется пакет PyGObject, который обеспечивает связывание базовых библиотек GObject, таких как Gtk, Gstreamer, WebKitGTK, Glib, GIO и многих других.
Несомненно, пакет PyGObject является наиболее предпочтительным для разработки приложений на Python и реализует доступ к основной базовой функциональности графического окружения Gnome, как показано на рисунке 1.2
Рисунок 1.1
Из которого следует, что PyGObject использует библиотеки glib, gobject и уже ранее упоминавшиеся бибилиотеки girepository и libffi для обеспечения доступа к написанной на C библиотеки libgtk-x.x.so в комбинации с дополнительными метаданными из сопровождающего файла динамической типизации Gtk-x.x.typelib и предоставляющей её интерфейсам Python
Кроме того, PyGObject прекрасно взаимодействует со следующими программными компонентами Gnome :
- Anaconda программа установки программного обеспечения в соответствии с используемым аппаратном обеспечением; широко задействуется RedHat и другими;
- D-Feet легкий в использовании отладчик D-Bus;
- Gaphor простейшая утилита UML и SysML моделирования;
- Girens клиент Plex для проигрывание видеороликов, просмотра TV и музыкальных видеоклипов с использованием библиотеки Plex;
- GNOME Music музыкальный клиент для Gnome;
- GNOME Tweak Tool настройка дополнительных опций Gnome;
- Gramps генеалогическое древо;
- Lollypop современный музыкальный проигрыватель;
- Meld утилита визуализации и слияния;
- MyPaint шустрый, тщательно-продуманный и легкий в использовании утилита для создания цифровых рисунков;
- Nicotine+ графический клиент для сетевого обмена файлами Soulseek по p2p;
- Orca утилита распознавания текста;
- Pithos радио клиент Pandora;
- Quod Libet библиотека музыкального проигрывателя Quod Libet;
- Pitivi – свободнораспростроняемый в открытых кодах видео редактор;
- Terminator – запуск всех терминалов в одном окне, в т.ч. удаленного доступа наподобие тех, что запускаются по протоколу SSH
Ниже перечисленные библиотек используют PyGObject для расширения функциональности в виде отдельных подключаемых плагинов или дополнительных бакендов:
- beets – библиотека музыкального менеджера и расстановщик тэгов MusicBrainz;
- gedit – текстовый редактор;
- matplotlib – библиотека Python для 2D графики;
- Totem – видеоплеер для Gnome
2. Использование PyGObject
2.1 Установка программного обеспечения
В операционной системе Debian OC GNU/Linux необходимо установить базовые пакеты реализующие поддержку интроспекции GObgect, таких как python3-gi-cairo, python3-gi и python-gi-dev, предоставляемые пакетом исходного кода pygobject , как показано в дампе 2.1.1
Дамп 2.1.1
$ sudo apt install python3-gi-cairo python3-gi python-gi-dev
При этом, скорее всего у Вас уже установлены первые два пакета, поэтому python-gi-dev рекомендую устанавливать по желанию.
2.2 Создание скелета программы
В листинге 2.2.1 приведен скелет программы gsshmgmt, которая выводит окно с названием "SSH Managment"
Листинг 2.2.1
1 from gi.repository import Gtk 2 import sys ... 25 class TopLevelWindow(Gtk.ApplicationWindow): 26 27 # constructor for a Gtk.ApplicationWindow 28 def __init__(self, app): 29 Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL, modal=True, title="The title of my program", application=app) ... 42 43 class MyApplication(Gtk.Application): 44 45 def __init__(self): 46 Gtk.Application.__init__(self) 47 48 def do_activate(self): 49 top = TopLevelWindow(self) 50 top.show_all() 51 52 def do_startup(self): 53 Gtk.Application.do_startup(self) 54 55 app = MyApplication() 56 exit_status = app.run(sys.argv) 57 sys.exit(exit_status) 58 ...
В строке 1-2 листинга 2.2.1 производится установка импорта библиотек GNOME через интроспекцию GObject. В этих двух строках мы производим импорт языковых привязок и библиотеки Gtk, которая содержит графические виджеты, используемые для создания приложений GNOME . При этом, как показано в строке 1, 2 и 4 листинга 2.2.2, необходимо указать какая именно совместимая версия библиотеки Gtk для нашего приложения будет подключаться модулем gi, реализующий языковое связывание интроспекции gobgect и написанной на языке программирования С библиотеки Gtk
Листинг 2.2.1
1 import gi 2 gi.require_version("Gtk", "3.0") 3 4 from gi.repository import Gtk ...
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os ...
Но, мало определить явно версию Gtk, в случае обращение к примитивам Gdk, ей нужно тоже определить требуему версию. Поэтому заголовок программы на Python будет иметь вид, как показано в дампе 2.2.3
Листинг 2.2.3
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 import os
4 import gi
5 gi.require_version("Gtk", "3.0")
6 gi.require_version("Gdk", "3.0")
7
8 from gi.repository import Gtk,Gdk
...
Как показано в строках 5 и 6 листинга 2.2.3, в первых строках кода необходимо указывать требуемые версии подключаемых библотек, которые будет использовать наша программа на Python, чтобы исключить неоднозначных ситуаций, наподобие той, что может сопровождаться диагностическими сообщениями, такими как "PyGIWarning: Gtk was imported without specifying a version first..." или "PyGIWarning: Gdk was imported without specifying a version first...".
В строках 25-41 листинга 2.2.1 декларируем класс TopLevelWindow, которое содержит основные элементы управления окна верхнего уровня на базе Gtk.ApplicationWindow, которое будет отображено и реализовать интерфейс пользователя в виде визуальных элеменов и форм управления.
В строках 43-53 листинга 2.2.1 декларируем класс MyApplication, который инициализирует и отображает окно верхнего уровня путем вызова метода:
- do_activate()для создания окна и его элементов управления, тем самым делает это окно главным, которое поразумевает завершение приложения после его закрытия; (строки 48-50 листинга 2.2.1);
- do_startup(), который осуществляет создание экземпляра объекта при первом запуске приложения (строки 51-52 листинга 2.2.1).
Кроме того, могут быть дополниетльно определены следующие методы:
- do_shutdown(), в котором определяются действия связаны с завершением работы приложения;
- do_open() открывает файлы и отображает их содержимое в окне или в элементе управления, выбранного в нем.
Порядок обращения к выше перечисленным методам будет следующим:
- первым будет вызван метод do_activate(), который не только создаст окно верхнего уровня, но и позволить выполнить задачи не связанные напрямую с его отображением;
- после, будет в зависимости от того как приложение запускается будет вызвано следующим либо метод do_activate() или do_open() ;
- Соответственно, последним будет вызван метод do_shutdown() в момент финализации, завершения работы приложения.
При этом, нужно учитывать, что приложение Gnome запускается в качестве первичного (single-instance) или вторичного экземпляра (second-instance). При этом по умолчанию, запущенный экземпляр приложения в Gnome будет первичным по умолчанию. Если пользователь попытается запустить второй экземпляр приложения Gnome, для первого экземпляра будут выполнены методы do_activate() и do_open()
Также, чтобы приложение не зависало на методе do_shutdown() следует использовать quit() после Gtk.Application.do_shutdown() , как показано в листинге 2.2.4
Листинг 2.2.4
... 78 class MyApplication(Gtk.Application): 79 80 stage = 0 81 82 def __init__(self): 83 self.stage += 1 84 print("%2d. Gtk.Application __init__ !!!" % self.stage ) 85 Gtk.Application.__init__(self) 86 87 def do_activate(self): 88 self.stage += 1 89 print("%2d. MyApplication :: do_activate !!!" % self.stage ) 90 top = TopLevelWindow(self) 91 top.show_all() 92 93 def do_open(self): 94 self.stage += 1 95 print("%2d. MyApplication :: do_open !!!" % self.stage ) 96 97 def do_startup(self): 98 self.stage += 1 99 print("%2d. MyApplication :: do_startup !!!" % self.stage ) 100 Gtk.Application.do_startup(self) 101 102 def do_shutdown(self): 103 self.stage += 1 104 print("%2d. MyApplication :: do_shutdown !!!" % self.stage ) 105 Gtk.Application.do_shutdown(self) 106 self.quit() ...
Реальный порядок запуска методов, определенных в строках 78-106 листинга 2.2.4, показан в дампе 2.2.5
Дамп 2.2.5
$ ./gsshmgmt.py 1. Gtk.Application __init__ !!! 2. TopLevelWindow :: do_startup !!! 3. TopLevelWindow :: do_activate !!! 4. TopLevelWindow :: do_shutdown !!!
В котором показан, вышеописанный порядок запуска конструктора __init__ методов TopLevelWindow :: do_startup(), TopLevelWindow :: do_activate() и TopLevelWindow :: do_shutdown(). При этом, чтобы избежать зависание на последнем в строку 84 листинга 2.2.6 добавлен self.quit()
2.3 Создание главного окна
В листинге 2.3.1 приведена, на сколько это возможно, детализация декларации главного окна и элементов управления в нем, как показано в листинге 2.3.1
Листинг 2.3.1
... .53 class TopLevelWindow(Gtk.ApplicationWindow): .54 55 # constructor for a Gtk.ApplicationWindow .56 def __init__(self, app): .57 Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL, modal=True, title="The title of my program", application=app) ...
Создание главного (type=Gtk.WindowType.TOPLEVEL) и модального (modal=True) окна верхнего уровня создоваемого приложения (application=app) производится с помощью конструктора __init__ базового класса Gtk.Window для класса Gtk.ApplicationWindow, как показано в строке 29 листинга 2.3.1
При этом, разработчику нужно учитывать, что Gtk.Window в GTK3 может иметь только один дочерний виджет. Поэтому самым простым решением было бы использовать ящик вертикального размещения виджетов на базе Gtk.Container
Но, так так как, на выданье версия Gtk4, определяем класс-обертку, чтобы абстрагировать TopLevelWindow от грядущих изменений при переходе с GTK3, как показано в листинге 2.3.2
Листинг 2.3.2
... .25 #BoxWrapper() .26 # .27 # will pack a child widget into the window as it can have one child only. .28 # .29 class BoxWrapper(Gtk.VBox): .30 .31 # method assigns a parent window to the widget by default. .32 def __init__(self, top): .33 Gtk.VBox.__init__(self,homogeneous=False,spacing=0) .34 .35 # metod adds a child to end of the box .36 def add(self,child): .37 self.pack_start(child,False, False, 0) 4 ... .53 class TopLevelWindow(Gtk.ApplicationWindow): .54 .55 # constructor for a Gtk.ApplicationWindow .56 def __init__(self, app): .57 ... .58 box = BoxWrapper(self) .59 self.add(box) .60 .61 # create a label .62 label = Gtk.Label() .63 # set the text of the label .64 label.set_text("Child widgets of the Vbox container") .65 # add the label to the window .67 box.add(label) ...
В результате выше описанных действий по реализации главного окна, на выходе должна получится картинка, как показано на рисунке 2.3.3
Рисунок 2.3.3
3. Библиография
3.1 Gnome Develeper.How to build, install and create a tar.xz of a Hello World program
3.3 Debian.org: Пакет исходного кода: pygobject
3.4 AskUbuntu. How to detect a computers physical screen size in gtk
3.5 StackOverflow.Com. Select certain monitor for going fullscreen with gtk
3.6 StackOverflow.Com. Show terminal output in a gui window using python gtk
3.7 StackOverflow.Com. How to make buttons different colours in python gtk3 using gi
3.8 Program Talk. gi.repository.Gtk.WindowType.TOPLEVEL
3.9 Python Code Examples for do startup
3.10 WiKi.Gnome. Using GtkApplication
3.11 Gnome Develeper. Class GtkApplication
3.12 StackOverflow.Com. Behaviour of increment and decrement operators in python