GTK4 と GStreamer の資料収集。
から分けた。
GTK3 gi.require_version('Gtk', '3.0')
minimum
# gtk3
import gi
gi.require_version("Gtk", "3.0") # 👈
from gi.repository import Gtk
win = Gtk.Window()
win.connect("destroy", Gtk.main_quit) # 👈
win.show_all() # 👈
Gtk.main() # 👈
widgets
Gtk.TreeView
C言語
Gtk.DrawingArea
GLArea(OpenGL)
GTK4 gi.require_version('Gtk', '4.0')
reference
Gtk4初手にオススメ
Gtk4チュートリアル
rust の GTK4。python 向けの GTK3 より参考になるかも
Gnome向け。動かない。libadwaita
GTK3との違い
- gi.require_version('Gtk', '3.0') => '4.0'
GTK4で無くなった
- Gtk.main_quit
- show_all()
- Gtk.main()
minimum
# gtk4
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk
def on_activate(app):
win = Gtk.ApplicationWindow(application=app)
btn = Gtk.Button(label="Hello, World!")
btn.connect('clicked', lambda x: win.close())
win.set_child(btn)
win.present()
app = Gtk.Application(application_id='org.gtk.Example')
app.connect('activate', on_activate)
app.run(None)
継承方式
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk
class Window(Gtk.ApplicationWindow):
def __init__(self, app) -> None:
super().__init__(application=app)
class Application(Gtk.Application):
def __init__(self) -> None:
super().__init__()
def do_activate(self):
win = Window(self)
win.present()
app = Application()
app.run()
GSK / Graphene
do_snapshot
GStreamer gi.require_version('Gst', '1.0')
オススメ(sintel_trailer-480p.webm への URL をローカルにダウンロードして "file:///" に書き換えないと動かなかった。Gtk3 -> Gtk4 の書き換え必要)
python2 + gtk2? 。読み替えが必要。
GstGL
Gtk と GStreamer の連携
Window 全体が VIDEO OVERLAY されちゃう
on_realize
Windows上のGtk4でのWindowハンドル取得例。
# this function is called when the GUI toolkit creates the physical window
# that will hold the video
# at this point we can retrieve its handler and pass it to GStreamer
# through the XOverlay interface
def on_realize(self, widget: Gtk.DrawingArea):
window_handle = self.get_native().get_surface().get_handle()
# pass it to playbin, which implements XOverlay and will forward
# it to the video sink
self.player.playbin.set_window_handle(window_handle)
pygobject と gobject-introspection
gobject-introspection(libgirepository) が GLIB(GObject) のリフレクションライブラリのようで、
pygobject はこのライブラリのユーザー。
gobject-introspection が動作するには対象の dll に対して gir とそこから生成される typelib が正しく配置される必要がある。
あとから gir と typelib を追加すると pygobject の使えるオブジェクトが増える。
ls C:/gnome/share/gir-1.0/
DBus-1.0.gir GdkPixbuf-2.0.gir Pango-1.0.gir freetype2-2.0.gir
DBusGLib-1.0.gir GdkPixdata-2.0.gir PangoCairo-1.0.gir gir-1.2.rnc
GIRepository-2.0.gir GdkWin32-4.0.gir PangoFT2-1.0.gir libxml2-2.0.gir
GL-1.0.gir Gio-2.0.gir PangoFc-1.0.gir win32-1.0.gir
GLib-2.0.gir Graphene-1.0.gir PangoOT-1.0.gir xfixes-4.0.gir
GModule-2.0.gir Gsk-4.0.gir Vulkan-1.0.gir xft-2.0.gir
GObject-2.0.gir Gtk-4.0.gir cairo-1.0.gir xlib-2.0.gir
Gdk-4.0.gir HarfBuzz-0.0.gir fontconfig-2.0.gir xrandr-1.3.gir
ls c:/gnome/lib/girepository-1.0
DBus-1.0.typelib Gio-2.0.typelib cairo-1.0.typelib
DBusGLib-1.0.typelib Graphene-1.0.typelib fontconfig-2.0.typelib
GIRepository-2.0.typelib Gsk-4.0.typelib freetype2-2.0.typelib
GL-1.0.typelib Gtk-4.0.typelib libxml2-2.0.typelib
GLib-2.0.typelib HarfBuzz-0.0.typelib win32-1.0.typelib
GModule-2.0.typelib Pango-1.0.typelib xfixes-4.0.typelib
GObject-2.0.typelib PangoCairo-1.0.typelib xft-2.0.typelib
Gdk-4.0.typelib PangoFT2-1.0.typelib xlib-2.0.typelib
GdkPixbuf-2.0.typelib PangoFc-1.0.typelib xrandr-1.3.typelib
GdkPixdata-2.0.typelib PangoOT-1.0.typelib
GdkWin32-4.0.typelib Vulkan-1.0.typelib
この gir と typelib を生成するためのツールは、gobject-introspection
のインストール時に作成されます。
g-ir-compiler で gir から typelib を作る。
pygobject(libgirepository) は typelib を参照していて、gir は見ていないぽい。
gtk や gstreamer など gir と typelib を生成して python から使いたいライブラリは、gobject-introspection
より後にビルドする必要があります。
gir のファイルパスは %PREFIX%/shared/gir-1.0/
。
typelib のファイルパスは %PREFIX%/lib/girepository-1.0
。
環境変数は GI_TYPELIB_PATH
。
language server
pygobject のインテリセンスが効くようにする。
Gtk 4.0 の型ヒントを生成する
> git clone https://github.com/pygobject/pygobject-stubs
> cd pygobject-stubs
pygobject-stubs> py .\tools\generate.py Gtk 4.0 > "C:\Python311\Lib\site-packages\gi-stubs\repository\Gtk.pyi"
python で対象モジュールを実際に import して生成しています。
import gi
gi.rquire_version('Gtk', '4.0')
from gi.repository import Gtk
for key in dir(Gtk):
value = getattr(Gtk, key)
# value の情報を調べる
xml から型ヒントを作る
GObject の場合 gir ファイルから stub を生成できる。
vscode から使うときにいい感じになった。
extension module
の関数は型情報がありません。
pylance とかは __doc__に仕込んだものを見つけてくれるかもしれない。
// C の Python 関数定義
// def func(*args, **keys): と見える
static PyObject *func(PyObject *self, PyObject *args);
C 言語など実装側では型情報分かっているので、そこから stub を作ってやると使い勝手が良くなります(bpy や qt など)。
import 時の挙動
DynamicImporter で typelib 情報から python module を動的にロードしている。
- gi.require_version('Gtk', '3.0')
- from gi.repository import Gtk # namespace Gtk
- DynamicImporter typelib (lib/girepository-1.0/Gtk-3.0.typelib)
- override(python で便利関数追加など)
といった感じで動く。
override は便利だけど他言語と乖離してドキュメントが読みにくくなる弱点がある。
参考
DynamicImporter
import sys
from ..importer import DynamicImporter
sys.meta_path.append(DynamicImporter('gi.repository')) # 👈
del DynamicImporter
del sys
int main(void) {
GError *error = NULL;
auto repository = g_irepository_get_default();
g_irepository_require(repository, "GLib", "2.0", {}, &error);
if (error) {
g_error("ERROR: %s\n", error->message);
return 1;
}
auto info = g_irepository_find_by_name(repository, "GLib", "MainLoop");
if (!info) {
g_error("ERROR: %s\n", "Could not find GLib.MainLoop");
return 1;
}
auto type = g_base_info_get_type(info);
if (!type) {
g_error("ERROR: %s\n", "Could not find GLib.MainLoop type");
return 2;
}
site-packages.gi.overrides
GIR からの自動生成に、手書きの python で型を拡張して便利関数を生やしている。
new 関数は gir 由来なのに対して、コンストラクター init や演算子オーバーロードなど。