GTK GUI with PyGObject (2)

Date: 2021/07/13 (initial publish), 2021/07/24 (last update)

Source: en/note-00015.md

Previous Post Top Next Post

TOC

Example: Static simple widgets into GUI

Dividing area into smaller subdivided areas are mostly done by GtkBox or GtkGrid under the “Containers” button.

As a starter, I put GtkBox.

Then I placed 2 simple “Control” widgets and a simple GtkLabel “Display” widget as an easy starter:

I set IDs for these widgets basically by dropping “Gtk” from the GTk class names. Then set up signal handlers in the right panel.

ID/Class name Widget Signal Signal handler
simple1 GtkWindow destroy onDestroy
button GtkButton pressed onButtonPressed
entry GtkEntry changed onEntryChanged
label GtkLabel

Then Glade screen looks like:

The Glade screen

How to create a simple GUI program

Now we are ready to use this from simple1.py:

import gi

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


@Gtk.Template(filename="simple1.ui")
class SimpleWindow(Gtk.Window):
    # corresponding name in XML 'class' attribute for this class
    __gtype_name__ = "simple1"
    # corresponding name in XML 'id' attribute sets this class member variable
    label = Gtk.Template.Child()
    # class member variable
    entry_text = ""

    @Gtk.Template.Callback()
    def onDestroy(self, *args):
        Gtk.main_quit()

    @Gtk.Template.Callback()
    def onButtonPressed(self, widget):
        print("=" * 80)
        print("Button label:    " + widget.get_label())
        print("Entered text:    " + self.entry_text)
        # This is right, I think.
        self.label.set_label(self.entry_text)

    @Gtk.Template.Callback()
    def onEntryChanged(self, widget):
        self.entry_text = widget.get_text()


window = SimpleWindow()
window.show()

Gtk.main()

The meaning of “@…” is described in Decorator in PEP 318.

Running this with python3 simple1.py will start the GUI as:

Run simple1

Please play with this GUI while looking at your terminal outputs.

Here, I am using the signal handler which uses the call back functions which set class variables in this example code. Now the rationale to use the class which generates functions and associated data is clear to me. It is a good start but this is not sufficient experience to make useful GUI since we still lack examples to use “Control” and “Display” widgets.

How Glade generated XML looks

Just in case I forget which items were selected via Glade session, here is the Glade generated XML simple1.ui:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <template class="simple1" parent="GtkWindow">
    <property name="can-focus">False</property>
    <signal name="destroy" handler="onDestroy" swapped="no"/>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkButton" id="button">
            <property name="label" translatable="yes">Press this to update</property>
            <property name="visible">True</property>
            <property name="can-focus">True</property>
            <property name="receives-default">True</property>
            <signal name="pressed" handler="onButtonPressed" swapped="no"/>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkEntry" id="entry">
            <property name="visible">True</property>
            <property name="can-focus">True</property>
            <signal name="changed" handler="onEntryChanged" swapped="no"/>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
      </object>
    </child>
  </template>
</interface>
Previous Post Top Next Post