diff options
author | Mat <mail@mathias.is> | 2022-12-01 23:59:27 +0200 |
---|---|---|
committer | Christoph Reiter <reiter.christoph@gmail.com> | 2023-03-22 10:10:45 +0000 |
commit | fa0b0e258aff23dded18aa3705791299a63d7b9a (patch) | |
tree | 027376fe1275d8857cc00fa1b52b3b080d5f1b07 /docs | |
parent | 4143b667e85969f8f638a255c743b0c5b15af677 (diff) | |
download | pygobject-fa0b0e258aff23dded18aa3705791299a63d7b9a.tar.gz |
Update docs and code examples to GTK 4
Diffstat (limited to 'docs')
-rw-r--r-- | docs/further.rst | 5 | ||||
-rw-r--r-- | docs/getting_started.rst | 45 | ||||
-rwxr-xr-x | docs/guide/code/cairo-demo.py | 234 | ||||
-rw-r--r-- | docs/guide/gtk_template.rst | 21 | ||||
-rw-r--r-- | docs/guide/threading.rst | 84 | ||||
-rw-r--r-- | docs/index.rst | 41 | ||||
-rw-r--r-- | docs/packagingguide.rst | 4 |
7 files changed, 220 insertions, 214 deletions
diff --git a/docs/further.rst b/docs/further.rst index 69223f50..e28c1291 100644 --- a/docs/further.rst +++ b/docs/further.rst @@ -2,8 +2,11 @@ Further Resources ================= +`GNOME Developer Documentation <https://developer.gnome.org/documentation/tutorials/beginners.html>`__ + Tutorials for creating a GNOME application using PyGObject, GTK 4 and Libadwaita. + `Python GTK 3 Tutorial <https://python-gtk-3-tutorial.readthedocs.io>`__ - Many examples showing how to build an application using PyGObject and GTK. + Many examples showing how to build an application using PyGObject and GTK 3. `Python GI API Reference <https://lazka.github.io/pgi-docs>`__ Auto generated API documentation for many libraries accessible through diff --git a/docs/getting_started.rst b/docs/getting_started.rst index e6921af8..01874efa 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -13,14 +13,27 @@ the following content and save it somewhere: .. code:: python + import sys + import gi - gi.require_version("Gtk", "3.0") - from gi.repository import Gtk - window = Gtk.Window(title="Hello World") - window.show() - window.connect("destroy", Gtk.main_quit) - Gtk.main() + gi.require_version("Gtk", "4.0") + from gi.repository import GLib, Gtk + + + class MyApplication(Gtk.Application): + def __init__(self): + super().__init__(application_id="com.example.MyGtkApplication") + GLib.set_application_name('My Gtk Application') + + def do_activate(self): + window = Gtk.ApplicationWindow(application=self, title="Hello World") + window.present() + + + app = MyApplication() + exit_status = app.run(sys.argv) + sys.exit(exit_status) Before we can run the example application we need to install PyGObject, GTK and their dependencies. Follow the instructions for your platform below. @@ -45,8 +58,8 @@ libraries. There are also typing stubs available here `PyGObject-stubs <https:// #) Follow the instructions on the page for setting up the basic environment #) Run ``C:\msys64\mingw64.exe`` - a terminal window should pop up #) Execute ``pacman -Suy`` -#) Execute ``pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-gobject`` -#) To test that GTK 3 is working you can run ``gtk3-demo`` +#) Execute ``pacman -S mingw-w64-x86_64-gtk4 mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-gobject`` +#) To test that GTK is working you can run ``gtk4-demo`` #) Copy the ``hello.py`` script you created to ``C:\msys64\home\<username>`` #) In the mingw32 terminal execute ``python3 hello.py`` - a window should appear. @@ -61,13 +74,13 @@ libraries. There are also typing stubs available here `PyGObject-stubs <https:// Installing the system provided PyGObject: #) Open a terminal - #) Execute ``sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0`` + #) Execute ``sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-4.0`` #) Change the directory to where your ``hello.py`` script can be found (e.g. ``cd Desktop``) #) Run ``python3 hello.py`` Installing from PyPI with pip: #) Open a terminal and enter your virtual environment - #) Execute ``sudo apt install libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-3.0`` + #) Execute ``sudo apt install libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-4.0`` to install the build dependencies and GTK #) Execute ``pip3 install pycairo`` to build and install Pycairo #) Execute ``pip3 install PyGObject`` to build and install PyGObject @@ -85,13 +98,13 @@ Installing from PyPI with pip: Installing the system provided PyGObject: #) Open a terminal - #) Execute ``sudo dnf install python3-gobject gtk3`` + #) Execute ``sudo dnf install python3-gobject gtk4`` #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` Installing from PyPI with pip: #) Open a terminal and enter your virtual environment - #) Execute ``sudo dnf install gcc gobject-introspection-devel cairo-gobject-devel pkg-config python3-devel gtk3`` + #) Execute ``sudo dnf install gcc gobject-introspection-devel cairo-gobject-devel pkg-config python3-devel gtk4`` to install the build dependencies and GTK #) Execute ``pip3 install pycairo`` to build and install Pycairo #) Execute ``pip3 install PyGObject`` to build and install PyGObject @@ -106,13 +119,13 @@ Installing from PyPI with pip: Installing the system provided PyGObject: #) Open a terminal - #) Execute ``sudo pacman -S python-gobject gtk3`` + #) Execute ``sudo pacman -S python-gobject gtk4`` #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` Installing from PyPI with pip: #) Open a terminal and enter your virtual environment - #) Execute ``sudo pacman -S python cairo pkgconf gobject-introspection gtk3`` + #) Execute ``sudo pacman -S python cairo pkgconf gobject-introspection gtk4`` to install the build dependencies and GTK #) Execute ``pip3 install pycairo`` to build and install Pycairo #) Execute ``pip3 install PyGObject`` to build and install PyGObject @@ -127,7 +140,7 @@ Installing from PyPI with pip: Installing the system provided PyGObject: #) Open a terminal - #) Execute ``sudo zypper install python3-gobject python3-gobject-Gdk typelib-1_0-Gtk-3_0 libgtk-3-0`` + #) Execute ``sudo zypper install python3-gobject python3-gobject-Gdk typelib-1_0-Gtk-4_0 libgtk-4-1`` #) Change the directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` @@ -148,7 +161,7 @@ Installing from PyPI with pip: #) Go to https://brew.sh/ and install homebrew #) Open a terminal -#) Execute ``brew install pygobject3 gtk+3`` +#) Execute ``brew install pygobject3 gtk4`` #) Change the working directory to where your ``hello.py`` script can be found #) Run ``python3 hello.py`` diff --git a/docs/guide/code/cairo-demo.py b/docs/guide/code/cairo-demo.py index f5ac1122..17a01b84 100755 --- a/docs/guide/code/cairo-demo.py +++ b/docs/guide/code/cairo-demo.py @@ -1,133 +1,125 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ Based on cairo-demo/X11/cairo-demo.c """ import cairo import gi -gi.require_version("Gtk", "3.0") + +gi.require_version('Gtk', '4.0') from gi.repository import Gtk SIZE = 30 -def triangle(ctx): - ctx.move_to(SIZE, 0) - ctx.rel_line_to(SIZE, 2 * SIZE) - ctx.rel_line_to(-2 * SIZE, 0) - ctx.close_path() - - -def square(ctx): - ctx.move_to(0, 0) - ctx.rel_line_to(2 * SIZE, 0) - ctx.rel_line_to(0, 2 * SIZE) - ctx.rel_line_to(-2 * SIZE, 0) - ctx.close_path() - - -def bowtie(ctx): - ctx.move_to(0, 0) - ctx.rel_line_to(2 * SIZE, 2 * SIZE) - ctx.rel_line_to(-2 * SIZE, 0) - ctx.rel_line_to(2 * SIZE, -2 * SIZE) - ctx.close_path() - - -def inf(ctx): - ctx.move_to(0, SIZE) - ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0) - ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0) - ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, - 2 * SIZE, 0) - ctx.rel_curve_to(-SIZE, -SIZE, - 2 * SIZE, -SIZE, - 2 * SIZE, 0) - ctx.close_path() - - -def draw_shapes(ctx, x, y, fill): - ctx.save() - - ctx.new_path() - ctx.translate(x + SIZE, y + SIZE) - bowtie(ctx) - if fill: - ctx.fill() - else: - ctx.stroke() - - ctx.new_path() - ctx.translate(3 * SIZE, 0) - square(ctx) - if fill: - ctx.fill() - else: - ctx.stroke() - - ctx.new_path() - ctx.translate(3 * SIZE, 0) - triangle(ctx) - if fill: - ctx.fill() - else: - ctx.stroke() - - ctx.new_path() - ctx.translate(3 * SIZE, 0) - inf(ctx) - if fill: - ctx.fill() - else: - ctx.stroke() - - ctx.restore() - - -def fill_shapes(ctx, x, y): - draw_shapes(ctx, x, y, True) - - -def stroke_shapes(ctx, x, y): - draw_shapes(ctx, x, y, False) - - -def draw(da, ctx): - ctx.set_source_rgb(0, 0, 0) - - ctx.set_line_width(SIZE / 4) - ctx.set_tolerance(0.1) - - ctx.set_line_join(cairo.LINE_JOIN_ROUND) - ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0) - stroke_shapes(ctx, 0, 0) - - ctx.set_dash([], 0) - stroke_shapes(ctx, 0, 3 * SIZE) - - ctx.set_line_join(cairo.LINE_JOIN_BEVEL) - stroke_shapes(ctx, 0, 6 * SIZE) - - ctx.set_line_join(cairo.LINE_JOIN_MITER) - stroke_shapes(ctx, 0, 9 * SIZE) - - fill_shapes(ctx, 0, 12 * SIZE) - - ctx.set_line_join(cairo.LINE_JOIN_BEVEL) - fill_shapes(ctx, 0, 15 * SIZE) - ctx.set_source_rgb(1, 0, 0) - stroke_shapes(ctx, 0, 15 * SIZE) - - -def main(): - win = Gtk.Window() - win.connect('destroy', lambda w: Gtk.main_quit()) - win.set_default_size(450, 550) - - drawingarea = Gtk.DrawingArea() - win.add(drawingarea) - drawingarea.connect('draw', draw) - - win.show_all() - Gtk.main() - +class Application(Gtk.Application): + + def do_activate(self): + window = Gtk.ApplicationWindow(application=self, default_width=450, default_height=600) + + drawing_area = Gtk.DrawingArea() + drawing_area.set_draw_func(self.draw) + window.set_child(drawing_area) -if __name__ == '__main__': - main() + window.present() + + def triangle(self, ctx): + ctx.move_to(SIZE, 0) + ctx.rel_line_to(SIZE, 2 * SIZE) + ctx.rel_line_to(-2 * SIZE, 0) + ctx.close_path() + + def square(self, ctx): + ctx.move_to(0, 0) + ctx.rel_line_to(2 * SIZE, 0) + ctx.rel_line_to(0, 2 * SIZE) + ctx.rel_line_to(-2 * SIZE, 0) + ctx.close_path() + + def bowtie(self, ctx): + ctx.move_to(0, 0) + ctx.rel_line_to(2 * SIZE, 2 * SIZE) + ctx.rel_line_to(-2 * SIZE, 0) + ctx.rel_line_to(2 * SIZE, -2 * SIZE) + ctx.close_path() + + def inf(self, ctx): + ctx.move_to(0, SIZE) + ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0) + ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0) + ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, - 2 * SIZE, 0) + ctx.rel_curve_to(-SIZE, -SIZE, - 2 * SIZE, -SIZE, - 2 * SIZE, 0) + ctx.close_path() + + def draw_shapes(self, ctx, x, y, fill): + ctx.save() + + ctx.new_path() + ctx.translate(x + SIZE, y + SIZE) + self.bowtie(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3 * SIZE, 0) + self.square(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3 * SIZE, 0) + self.triangle(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3 * SIZE, 0) + self.inf(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.restore() + + def fill_shapes(self, ctx, x, y): + self.draw_shapes(ctx, x, y, True) + + def stroke_shapes(self, ctx, x, y): + self.draw_shapes(ctx, x, y, False) + + def draw(self, da, ctx, width, height): + ctx.set_source_rgb(0, 0, 0) + + ctx.set_line_width(SIZE / 4) + ctx.set_tolerance(0.1) + + ctx.set_line_join(cairo.LINE_JOIN_ROUND) + ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0) + self.stroke_shapes(ctx, 0, 0) + + ctx.set_dash([], 0) + self.stroke_shapes(ctx, 0, 3 * SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_BEVEL) + self.stroke_shapes(ctx, 0, 6 * SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_MITER) + self.stroke_shapes(ctx, 0, 9 * SIZE) + + self.fill_shapes(ctx, 0, 12 * SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_BEVEL) + self.fill_shapes(ctx, 0, 15 * SIZE) + ctx.set_source_rgb(1, 0, 0) + self.stroke_shapes(ctx, 0, 15 * SIZE) + + +app = Application() +app.run() diff --git a/docs/guide/gtk_template.rst b/docs/guide/gtk_template.rst index 3e340600..2ba8324c 100644 --- a/docs/guide/gtk_template.rst +++ b/docs/guide/gtk_template.rst @@ -69,27 +69,6 @@ Python attribute names that are different to the XML values: pass -To add widgets to the built-in child of a parent, describe the built-in widget -in the XML with its ``child`` element having an ``internal-child`` attribute set -to the name of the built-in widget: - -.. code-block:: XML - - <interface> - <template class="example2" parent="GtkDialog"> - <child internal-child="vbox"> - <object class="GtkBox"> - <child> - <object class="GtkButton" id="hello_button"> - <property name="label">Hello World</property> - </object> - </child> - </object> - </child> - </template> - </interface> - - Subclasses that declare ``__gtype_name__`` can be used as objects in the XML: .. code-block:: python diff --git a/docs/guide/threading.rst b/docs/guide/threading.rst index fea26d18..da3cd7f6 100644 --- a/docs/guide/threading.rst +++ b/docs/guide/threading.rst @@ -31,37 +31,38 @@ while still showing feedback on the progress in a window. import threading import time + import gi + gi.require_version('Gtk', '4.0') from gi.repository import GLib, Gtk, GObject - def app_main(): - win = Gtk.Window(default_height=50, default_width=300) - win.connect("destroy", Gtk.main_quit) + class Application(Gtk.Application): - progress = Gtk.ProgressBar(show_text=True) - win.add(progress) + def do_activate(self): + window = Gtk.ApplicationWindow(application=self) + self.progress = Gtk.ProgressBar(show_text=True) - def update_progess(i): - progress.pulse() - progress.set_text(str(i)) + window.set_child(self.progress) + window.present() + + thread = threading.Thread(target=self.example_target) + thread.daemon = True + thread.start() + + def update_progess(self, i): + self.progress.pulse() + self.progress.set_text(str(i)) return False - def example_target(): + def example_target(self): for i in range(50): - GLib.idle_add(update_progess, i) + GLib.idle_add(self.update_progess, i) time.sleep(0.2) - win.show_all() - - thread = threading.Thread(target=example_target) - thread.daemon = True - thread.start() - - if __name__ == "__main__": - app_main() - Gtk.main() + app = Application() + app.run() The example shows a simple window containing a progress bar. After everything @@ -167,15 +168,17 @@ operation. .. code:: python import time + import gi + gi.require_version('Gtk', '4.0') from gi.repository import Gio, GLib, Gtk - class DownloadWindow(Gtk.Window): + class DownloadWindow(Gtk.ApplicationWindow): - def __init__(self): - super(DownloadWindow, self).__init__( - default_width=500, default_height=400, title="Async I/O Example") + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs, default_width=500, default_height=400, + title="Async I/O Example") self.cancellable = Gio.Cancellable() @@ -186,22 +189,22 @@ operation. self.start_button = Gtk.Button(label="Load") self.start_button.connect("clicked", self.on_start_clicked) - textview = Gtk.TextView() + textview = Gtk.TextView(vexpand=True) self.textbuffer = textview.get_buffer() scrolled = Gtk.ScrolledWindow() - scrolled.add(textview) + scrolled.set_child(textview) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, - border_width=12) - box.pack_start(self.start_button, False, True, 0) - box.pack_start(self.cancel_button, False, True, 0) - box.pack_start(scrolled, True, True, 0) + margin_start=12, margin_end=12, margin_top=12, margin_bottom=12) + box.append(self.start_button) + box.append(self.cancel_button) + box.append(scrolled) - self.add(box) + self.set_child(box) def append_text(self, text): iter_ = self.textbuffer.get_end_iter() - self.textbuffer.insert(iter_, "[%s] %s\n" % (str(time.time()), text)) + self.textbuffer.insert(iter_, f"[{time.time()}] {text}\n") def on_start_clicked(self, button): button.set_sensitive(False) @@ -221,22 +224,25 @@ operation. try: succes, content, etag = source_object.load_contents_finish(result) except GLib.GError as e: - self.append_text("Error: " + e.message) + self.append_text(f"Error: {e.message}") else: content_text = content[:100].decode("utf-8") - self.append_text("Got content: " + content_text + "...") + self.append_text(f"Got content: {content_text}...") finally: self.cancellable.reset() self.cancel_button.set_sensitive(False) self.start_button.set_sensitive(True) - if __name__ == "__main__": - win = DownloadWindow() - win.show_all() - win.connect("destroy", Gtk.main_quit) + class Application(Gtk.Application): + + def do_activate(self): + window = DownloadWindow(application=self) + window.present() + - Gtk.main() + app = Application() + app.run() The example uses the asynchronous version of :meth:`Gio.File.load_contents` to @@ -249,7 +255,7 @@ the content of the web page we wanted. .. code:: python - file = Gio.File.new_for_uri("http://python-gtk-3-tutorial.readthedocs.org/") + file = Gio.File.new_for_uri("https://developer.gnome.org/documentation/tutorials/beginners.html") try: status, contents, etag_out = file.load_contents(None) except GLib.GError: diff --git a/docs/index.rst b/docs/index.rst index f6823031..1addb839 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -30,21 +30,34 @@ If you want to write a Python application for `GNOME <https://www.gnome.org/>`__ or a Python GUI application using GTK, then -PyGObject is the way to go. For more information on specific libraries check -out the "`Python GTK 3 Tutorial -<https://python-gtk-3-tutorial.readthedocs.io>`__" and the "`Python GI API +PyGObject is the way to go. To get started, check out the "`GNOME Developer Documentation +<https://developer.gnome.org/documentation/tutorials/beginners.html>`__". For more +information on specific libraries, check out the "`Python GI API Reference <https://lazka.github.io/pgi-docs>`__". .. code:: python + import sys + import gi - gi.require_version("Gtk", "3.0") - from gi.repository import Gtk - window = Gtk.Window(title="Hello World") - window.show() - window.connect("destroy", Gtk.main_quit) - Gtk.main() + gi.require_version("Gtk", "4.0") + from gi.repository import GLib, Gtk + + + class MyApplication(Gtk.Application): + def __init__(self): + super().__init__(application_id="com.example.MyGtkApplication") + GLib.set_application_name("My Gtk Application") + + def do_activate(self): + window = Gtk.ApplicationWindow(application=self, title="Hello World") + window.present() + + + app = MyApplication() + exit_status = app.run(sys.argv) + sys.exit(exit_status) How does it work? @@ -55,12 +68,12 @@ How does it work? :height: 222px :align: center -PyGObject uses `glib <https://developer.gnome.org/glib/stable/>`__, `gobject -<https://developer.gnome.org/gobject/stable/>`__, `girepository -<https://developer.gnome.org/gi/stable/>`__, `libffi +PyGObject uses `glib <https://docs.gtk.org/glib/>`__, `gobject +<https://docs.gtk.org/gobject/>`__, `girepository +<https://gnome.pages.gitlab.gnome.org/gobject-introspection/girepository/GIRepository.html>`__, `libffi <https://sourceware.org/libffi/>`__ and other libraries to access the C -library (libgtk-3.so) in combination with the additional metadata from the -accompanying typelib file (Gtk-3.0.typelib) and dynamically provides a Python +library (libgtk-4.so) in combination with the additional metadata from the +accompanying typelib file (Gtk-4.0.typelib) and dynamically provides a Python interface based on that information. diff --git a/docs/packagingguide.rst b/docs/packagingguide.rst index e1715eb9..d9536388 100644 --- a/docs/packagingguide.rst +++ b/docs/packagingguide.rst @@ -4,7 +4,7 @@ Packaging Guide Some notes on how to package PyGObject Source packages can be found at -https://ftp.gnome.org/pub/GNOME/sources/pygobject +https://download.gnome.org/sources/pygobject Existing Packages: @@ -40,6 +40,6 @@ Build dependencies: Test Suite dependencies: * The runtime dependencies - * GTK 3 (optional) + * GTK 4 (optional) * pango (optional) * pycairo (optional) |