Paepoi

Paepoi » PyGObject Tips » PyGObject(aka PyGI) とは

PyGObject(aka PyGI) とは

Projects/PyGObject - GNOME Wiki!

PyGObject という名のモジュールは GTK2 時代にもありましたが別物です。
GObject Introspection というライブラリを使った Python バインデングです。
PyGI とも呼ばれていますが PyGObject という呼び名が一般的になったようです。

エンドユーザーは次世代 PyGtk と思えばいいでしょう。
PyGTK 自体は GTK2 ベースということで 2011 年に開発終了しています。

PyGtk のような独立プロジェクトによる静的なものではなく動的バインディングです。
結果 GTK+ の新機能がスクリプト言語からでも即時に利用できるようになりました。
gir 自体は Gjs, Perl 等の様々な言語から利用できます、今後はこれが主になるでしょう。

使い方

"""
import pygtk
pygtk.require("2.0")
import gtk
"""
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
# 参照
PyGtk     @ /usr/lib64/python2.7/site-packages/gtk-2.0/*
PyGObject @ /usr/lib64/girepository-1.0/*.typelib
このコードで上記の部分を参照します。
PyGObject は require しなければ自動的に新しいバージョン側を参照する。
(3.18 からはバージョン指定しないと警告が出るようになった...)

Python をよく知っている人は多分先頭文字が大文字なことに少々イラつくと思います。
GObject Introspection は Python のみのバインディングではないので従うしかない。

関数の書き方が C 言語とほぼ同様になり devhelp が理解しやすくなっています。
# gtk_button_new_from_stock(GTK_STOCK_OK)
Gtk.Button.new_from_stock(Gtk.STOCK_OK)

関数のバインドは PyGtk と同様に引数で値を得る関数はタプルとして戻り値となる。
""" C
gboolean result;
gchar* contents;

result = g_file_get_contents("hoge.txt", &contents, NULL, NULL);
"""

result, contents = GLib.file_get_contents("hoge.txt")

列挙体は大体こんな感じで変換できます。
'''
typedef enum {
  GTK_WINDOW_TOPLEVEL,
  GTK_WINDOW_POPUP
} GtkWindowType;
'''
Gtk.WindowType.TOPLEVEL

つまり PyGtk とは全く別物ですが互換性も多少考慮されているようです。
たとえばプロパティを読み書きする方法に props メソッドがあります。
下記のように PyGtk と同様にセットすることもできるようです。
# Convert '-' to '_'
tree.props.headers_visible = False
# or Compatibility PyGtk
tree.set_property("headers-visible", False)

GtkBox へのパッキングにデフォルト引数が無くなり全指定する必要あり。
GtkBox は GtkVBox, GtkHBox をまとめたものです。
GTK3 からは V,H で別れていたウイジェットは全部こうなります。
# PyGtk pack_start(child, expand=True, fill=True, padding=0)
# vbox = gtk.VBox()
# vbox.pack_start(label)

# PyGObject pack_start(child, expand, fill, padding)
vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0) # or HORIZONTAL
vbox.pack_start(label, False, False, 0)

イテレータ関連がポインタと同様の扱いになり戻り値で代入ではなく直接変更される。
たとえば GtkTreeSelection で入れ替えを行う場合は以下のようにコピーして書き換える。
等々、とにかく C 言語と同じように扱う必要があります。
# new
def on_item_up(self, widget, data=None):
    selection = self.treeview.get_selection()
    model, it = selection.get_selected()
    if it:
        itprev = it.copy()
        if model.iter_previous(itprev):
            model.swap(it, itprev)

その他にエラー処理の大半が例外を利用になっています。
引数に GError が含まれる関数はすべて try...except で例外を GError でキャッチです。
try 文を書かなくても使えますが動的言語の Python では実行時に例外になると親に raise される。
余談ですが Vala では明示的に書かないとコンパイル時に警告になります。
#!/usr/bin/env python3

"""
gboolean g_file_get_contents (  const gchar *filename,
                                gchar **contents,
                                gsize *length,
                                GError **error);
"""
from gi.repository import GLib

try:
    result, contents = GLib.file_get_contents("hoge.txt")
    if result:
        print(contents.decode())
except Exception as e:
    print("FileError: {0}".format(e))

PyGObject 3.12 からは GObject.threads_init() は不要になった。
マルチスレッドのアプリケーションを作らないなら関係ないですが。

同じく 3.12 からは NULL でいい末尾引数はすべて書かなくていいとなった。
GCancellable 部や user_data が無い場合のハンドラへの無駄な記述はもう不要です。
#on_button_clicked(self, widget, data=None):
on_button_clicked(self, widget):
    f = Gio.file_new_for_path(self.filename)
    #fstream = f.read(None)
    fstream = f.read()

3.14 から MenuButton のアイコンが三本線になった。
位置も変わったので覚書。
# Fedora 20
/usr/share/icons/gnome/scalable/emblems/emblem-system-symbolic.svg
# Fedora 21 Gear Icon
/usr/share/icons/Adwaita/scalable/emblems/emblem-system-symbolic.svg
# Fedora 21 Menu Button
/usr/share/icons/Adwaita/scalable/actions/open-menu-symbolic.svg
Copyright(C) sasakima-nao All rights reserved 2002 --- 2024.