How to access UI element from python?

I’m very new with the Gnome ecosystem.

The question: How to change the content (text / label) of a GtkLabel from Python from an Object ID?

Context:

1- You open Gnome Builder and create a new “Gnome Application” with Python.

2- You open the “Camblache” app and edit your main window UI file generated the step before and create a new GtkLabel and give it a new object ID.

3- You go back into your python file and, in the “do_activate” function, you try to target it by its ID… but fail miserably. you then realize again how it must have felt to be your student when you explained basic stuff completely foreign for them…

I wonder if it’s as simple as “win.getThat(‘objID’)” but after hours in the documentations I’m still out of luck.

Can someone point me in the right direction please ?

Thank you :slight_smile:

You probably want to start from the developer documentation for Python and GNOME:

You want Gtk.Template — PyGObject specifically

1 Like

Thank you for your response. That’s where I started indeed :slight_smile: They show how to create GtkLabel via GtkBuilder and so on… But I missed the part (Or it’s not in there) about how to target a UI element not created from the code but from the UI file by it’s ID. Maybe it’s not a concept present here ?

Thanks! I saw that one but I felt it only allowed to move “relatively” in the UI; Like imagine if the UI is made of 10 “layer” (Parent - child - child - ….) you would need to access every parents one by one to access the deepest child. Would it be possible to “just” specify the object ID of the desired element to “target” it ?

EDIT:

Oh ! I miss read this page indeed. Thank you. I’ll try.

If you’re using Gtk.Template then you use Gtk.Template.Child().

If you’re using Gtk.Buider directly—which you shouldn’t do, except for very simple demos—you use Gtk.Builder.get_object().

2 Likes

In reply to @ebassi and @bugaevc ; I’m now able to target the elements in the “root” child block; but not their child.

Here’s a part of my UI file;

<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.96.1 -->
<interface>
  <!-- interface-name window.ui -->
  <requires lib="Adw" version="1.0"/>
  <requires lib="gtk" version="4.0"/>
  <requires lib="libadwaita" version="1.7"/>
  <template class="CalculatorWindow" parent="AdwApplicationWindow">
    <property name="content">
      <object class="AdwToolbarView">
        <child type="top">
          <object class="AdwHeaderBar">
            <child type="end">
              <object class="GtkMenuButton">
                <property name="icon-name">open-menu-symbolic</property>
                <property name="primary">True</property>
                <property name="tooltip-text" translatable="yes">Main Menu</property>
              </object>
            </child>
          </object>
        </child>
        <child>
          <object class="GtkFrame" id="layerOne">
            <child>
              <object class="GtkFlowBox" id="layerTwo">
                <property name="max-children-per-line">5</property>
                <property name="orientation">vertical</property>
                <child>
                  <object class="GtkLabel" id="display"/>
                </child>
                <child>
...

I want to access the GtkLabel with the ID “display”. Could you help me find the right approach to get there ? is the function GTK.Template.Child can search recursively ?

Yes, GTK.Template.Child can give you a reference to any indirect child as well (in fact, to any named object anywhere in the .ui file, it doesn’t even have to be a descendant widget of your template object). For your case, you’re going to want to write something like this:

@Gtk.Template(...)
class CalculatorWindow(Adw.ApplicationWindow):
    __gtype_name__ = 'CalculatorWindow'

    # Our template child, a Gtk.Label named "display"
    display = Gtk.Template.Child()

    def __init__(self):
        self.display.set_text('Gtk.Template is cool!')
2 Likes

Okay. I think I got it. Thank you both for your patience.

So my mistakes;

  1. The variables names matter. ^^’ woops.
  2. I was in the main.py instead of the window.py.

And now I got a big part of the foundation I needed to go forward.

Thanks :slight_smile:

This understandably can be surprising :slightly_smiling_face:

In the typical case your object ID in the .ui file should match the Python variable name, and it all works out. If you want to name the Python variable something else, you can pass the object ID explicitly, like so:

display_label = Gtk.Template.Child('display')

I tried this but my other mistake (Being in the wrong file) made me think I did not understood back then. Now it all make sense. Thanks again ^^’