DEV Community

MoniqueLive
MoniqueLive

Posted on • Updated on

Python3 + GTK+3 + Glade + Templates = <3

Many software that you use on your Gnome environment could've been developed with Python. Apps like Gnome Music and Gnome Tweaks are some examples.

In this article I'll show you a minimal example in order to give you a foundation for your ideas. Let's go:

Create a basic layout on Glade:

GtkApplicationWindow

Stuff you need to pay attention to:

  • The top level component is a GtkApplicationWindow (you can find it under Toplevels button)
  • While it's selected, check the Composite checkbox on the farther right (super important!)
  • When you check the Composite checkbox the ID field becomes Class Name. Give it a name and save it, we'll use it soon
  • Give the button an ID and save it, we'll use it soon

With the Button selected, switch to the Signals tab:

Button Signals

  • Click on the Handler column on the clicked Signal row
  • Type the first letter of your button's name
  • Accept the suggestion (btnMain_clicked_cb, in my example) and save it, we'll use it soon

And that's it for Glade. Save your .glade file on your project dir.

Create a basic Python skeleton:

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gio, Gtk

import sys


#
# 1. our .glade file (may contain paths)
#
@Gtk.Template.from_file("a.glade")
class AppWindow(Gtk.ApplicationWindow):
    #
    # 2. the GtkApplicationWindow class
    #
    __gtype_name__ = "app_window"

    #
    # 3. the Button name we saved above
    #
    btnMain: Gtk.Button = Gtk.Template.Child()

    #
    # 4. the signal handler name we saved above
    #
    @Gtk.Template.Callback()
    def btnMain_clicked_cb(self, widget, **_kwargs):
        assert self.btnMain == widget
        print(widget.get_label())


class Application(Gtk.Application):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, application_id="dev.monique.Gtk1",
                         flags=Gio.ApplicationFlags.FLAGS_NONE, **kwargs)
        self.window = None

    def do_activate(self):
        self.window = self.window or AppWindow(application=self)
        self.window.present()


if __name__ == '__main__':
    Application().run(sys.argv)
Enter fullscreen mode Exit fullscreen mode

You'll also need to:

pip install PyGObject
Enter fullscreen mode Exit fullscreen mode

It may complain about missing libraries, just read the error output and install the missing dependencies (I had to apt install libcairo2-dev libgirepository1.0-dev)

With this code you'll be able to get started.

Good luck!

Top comments (6)

Collapse
 
jakoch5876 profile image
jakoch5876

Thank you for this post, very helpful and exactly what I was looking for.

Collapse
 
naruaika profile image
Naufan Rusyda Faikar

Woah, I just came to know that there is @Gtk.Template.Callback()! Thank you! I have been wondering this for a month or two!

Collapse
 
moniquelive profile image
MoniqueLive

It’s really poorly documented. But there’s a pull request with some documentation waiting to be accepted...

Collapse
 
naruaika profile image
Naufan Rusyda Faikar

It's good to know that! I actually have read the source code, but couldn't realized what the Callback is for.

Collapse
 
texxg profile image
T.xx

I just made my very 1st python GTK app and I have to agree with you, the documentation is poor. And it’s such a great shame, as the tooling is otherwise so great! I love Glade!

I had to dig up answers to my guestions all over the planet, but eventually found everything I was looking for.

I have planned on making a blog post of some of the things that were difficult to solve (because of the documentation), so hopefully someone finds it helpfull. I never understood that one could contribute the documentation as well?

I also wish there would still be build windows binaries for the GTK, I never got Zeep working in MSYS :( But with windows was a snap. I am new with MSYS as well.

Collapse
 
pplcc profile image
Peter P. • Edited

Thank you! It's 2024 and I haven't found that anywhere else. Maybe you could bold the "(super important!)" in the "Composite checkbox" item. I actually didn't do it and only read it the second time through.
To use this with the pyinstaller, I had to determine the glade path at runtime:

import os

current_dir = os.path.dirname(os.path.abspath(__file__))
glade_file_path = os.path.join(current_dir, "a.glade")

@Gtk.Template.from_file(glade_file_path)
class AppWindow(Gtk.ApplicationWindow):

Enter fullscreen mode Exit fullscreen mode