Previous Post | Top | Next Post |
TOC
Now that GTK4 is used in Debian/Bookworm in 2023, this section is getting outdated. The followings may be interesting to read:
My objective here is to learn efficient GUI programming with Glade and Python using Gtk.Builder class instead of calling widget classes directly and using decorators offered by Gtk.Templates.
I only touch on essential concepts in the order of practical importance and skip trivial points and points already addressed in The Python GTK+ 3 Tutorial.
GTK GUI situation
GTK3 GUI has been changing. (version 3.38.5, 2021-07, Debian Bullseye)
The Python GTK+ 3 Tutorial (as of 2021-07) goes as:
Gtk.UIManager, Gtk.Action, and Gtk.ActionGroup have been deprecated since GTK+ version 3.10 and should not be used in newly-written code. Use the Application framework instead.
I understand this is caused by App Menu Retirement. I see no Python based tutorial contents for creating modern Primary menu on the headbar using the client side decoration (CSD).
How do I do it? Unfortunately, many code examples in the upstream source tree and the tutorial tend to contain old deprecated practices. This is why I recorded my learning experiences here. (Actual my experiences were much more twisted and tangled. I have touched up my learning history to make it easy for me to recall how to do this again.)
Gtk 3 documentation for Python user
As usual with F/LOSS documents, there are too many similar documents including old ones out there.
These are the key documents:
- Reference documents:
- GTK+ 3 Reference Manual
(web and devhelp)
- This is written primarily for user writing code in C and uses C API names.
- Help contents displayed by Glade is this document.
- The one line descriptions of GTK+ Widgets names used in Glade are listed in its TOC page of “Part II. GTK+ Widgets and Objects”.
- Widget Gallery is included.
- PyGObject API Reference: Gtk 3.0
(web-only)
- This is part of PyGObject API Reference and uses Python API names.
- For coding in Python, this gives exact class names.
- GTK+ 3 Reference Manual
(web and devhelp)
- Tutorial and demo documents:
- The Python GTK+ 3 Tutorial.
- Good source of many GTK3 widget examples with direct Python-only coding style.
- Not much examples for use of Glade nor Gtk.Template technique.
- PyGObject
- Tutorials, code samples and platform demos in Python
- GTK+ widgets sample code
- Learn basic theory of GUI programming such as The Model/View/Controller design.
- Some parts still mention PyGtk indicating lack of recent updates. So be careful when reading.
- GTK+ widgets sample code
- The Python GTK+ 3 Tutorial.
Please note the GTK3’s C API name is spelled without “.” after “Gtk”, while the corresponding Python API name is spelled with “.” after “Gtk”.
Once you understand this, C API document becomes useful for Python programmer.
(If you see Python GTK document with their first part of GTK class name spelled in all lower case such as “gtk.Window” instead, you are reading old API based documents such as PyGTK 2.0 Reference Manual. Though they look similar, it is based on pre-GObject Introspection API and they are old. Keep away from them :-))
GUI programming workflow
Let’s recap my planned GUI programming workflow here.
- Design static GUI components with Glade
- Set the “composite” checkbox for the ID of the top GUI widget to make it “Class name”.
- You don’t need to worry too much on ID or call back function names. Just settle with automatic ones and deal them in Python code.
- Program dynamic GUI components with Python
- Use GObject Introspection to access GTK and associated libraries from simple Python code.
- Use
Gtk.Template.Child()
to create variables matching IDs in Glade XML to access widgets.Gtk.Template
can handle unmatched variable and ID combination gracefully
Know some limitations for Glade:
- Glade can set only one top level widget as “composit"=ON per one Glade XML
file.
- Decorator
Gtk.Template
approach requires one Glade XML file for each top level widget. - “Transient for:” in Glade is non-compatible with decorator
Gtk.Template
approach.
- Decorator
- When using Glade to create GUI, you are using Gtk.Buildable to create GUI widgets. So the “User data” parameter can take widgets defined in the Glade XML only. No external constant number nor string.
- Changing widget types or renaming IDs or shuffling position of widgets in Glade XML file are easier with the text editor than Glade.
- When Glade doesn’t work as expected while leaving
<placeholder/>
in the XML file, use the text editor to fix it.- Can’t add GtkHeaderBar to window with existing widgets / containers
- Read the pertinent API document carefully around parts mentioning Gtk.Buildable and use them
- Look for the successful XML file dealing the similar situation and imitate it.
Glade
Let me go step-by-step to use Glade to create GTK GUI in my way.
In order to understand what each Glade widget does, the TOC page “Part II. GTK+ Widgets and Objects” gives me the best one-line summary.
Please note Glade uses C API names.
For details on Python API, linked pages from the corresponding listed classes in the Gtk 3.0’s Classes page were valuable and gave me the most current insights.
Where to start GUI design
Looking at the way Glade is designed, it looked like I should start creating window design by clicking and moving item from selection in the top 4 big buttons to the center canvas.
Out of these 4 big buttons, the “Toplevels” button seems to be a good to start. Let’s check what are these GUI objects in “Toplevels”.
- Gtk.Window — Toplevel which can contain other widgets
- Gtk.OffscreenWindow — A toplevel to manage offscreen rendering of child widgets
- Gtk.ApplicationWindow — GtkWindow subclass with GtkApplication support
- Gtk.Dialog — Create popup windows
- Gtk….Dialog — Create specific purpose helper popup windows for typical use cases
- Gtk.Assistant — A widget used to guide users through multi-step operations
Since I want a simple GUI, GtkWindow seems to be a good starting point for the GUI programming learning experience for me now, though Gtk.ApplicationWindow seems to be a good starting point for serious applications in future
Glade generates GtkBuilder UI descriptions in a XML file and Gtk.Buildable consumes this XML file to create complicated widgets. Please pay attention to some of these linked pages talking how widgets are implemented in the Gtk.Buildable.
How to create the top bar embedded primary menu is tricky with GtkWindow. It looks like GtkHeaderBar under the “Containers” button is the one to be used. We will get back to this header bar topic later.
Please note GtkMenuBar is not the one to be used for creating the menu (marked as deprecated for Glade 3.38.2).
How to write a clean python code
Being a lazy person, I want to write a clean and easy python code using decorator technique as described in The Python GTK+ 3 Tutorial: 22.5. Gtk.Template. This is extremely terse. The upstream document is found at PyGObject: Docs » User Guide » Gtk.Template gives a bit more details. PyGObject API Reference under Gtk 3.0 » Classes has no mention of this Gtk.Template.
It’s best to check how this Gtk.Template is implemented to be confident.
This is found in the python3-gi package as
/usr/lib/python3/dist-packages/gi/_gtktemplate.py
imported from
/usr/lib/python3/dist-packages/gi/overrides/Gtk.py
. Reading these gives us
what exactly does this decorator does.
In order to use this decorator technique, the top level widget needs to be
declared as <template>
instead of <object>
in XML. For Glade, this
requires us to click the “Composite” checkbox next to ID entry box on the
right side panel to change “ID” to “Class Name” while focusing at the
top level widget
GtkWindow on
the left side panel for my simple example case here.
Let’s put “simple1” to “ID”/“Class Name” entry and see the difference in XML.
$ diff -u0 simple1.ui-ID simple1.ui
--- simple1.ui-ID 2021-07-18 07:29:13.744765698 +0900
+++ simple1.ui 2021-07-18 07:30:00.030723401 +0900
@@ -5 +5 @@
- <object class="GtkWindow" id="simple1">
+ <template class="simple1" parent="GtkWindow">
@@ -52 +52 @@
- </object>
+ </template>
Previous Post | Top | Next Post |