'Child' object has no attribute 'set_child'

I’m trying to understand why I can’t use the set_child method on a template child object (please see last line -3) :

class ModelObject(GObject.GObject):
    def __init__(self, name):
        super().__init__()
        self._name = name

    @GObject.Property(type=str)
    def name(self):
        return self._name

@Gtk.Template(resource_path='/org/yphil/matinee/window.ui')
class MatineeWindow(Adw.ApplicationWindow):
    __gtype_name__ = 'MatineeWindow'

    video = Gtk.Template.Child()
    scrolledWindow = Gtk.Template.Child()
    openDialog = Gtk.Template.Child()
    aboutDialog = Gtk.Template.Child()

    model = Gio.ListStore.new(ModelObject)
    model.append(ModelObject("one"))
    model.append(ModelObject("two"))
    model.append(ModelObject("three"))

    selection = Gtk.SingleSelection.new(model)
    factory = Gtk.BuilderListItemFactory.new_from_resource(None, 'listitem.ui')

    listView = Gtk.ListView.new(selection, factory)
    scrolledWindow.set_child(listView) # <= HERE

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

Gives:

File "/app/share/matinee/matinee/window.py", line 52, in MatineeWindow
    scrolledWindow.set_child(listView)
AttributeError: 'Child' object has no attribute 'set_child'

Here is my object in the window.ui file :

<object class="GtkScrolledWindow" id="scrolledWindow">
</object>

I was able to use the set_child() method of this very GtkScrolledWindow object before, specifically the child was a Gtk.TreeView, so why now can’t I add a child of type ListView to it?

PS - the listitem.ui file:


<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <template class="GtkListItem">
    <property name="child">
      <object class="GtkLabel">
        <property name="xalign">0</property>
        <binding name="label">
          <lookup name="name" type="__main__+Demo">
            <lookup name="item">GtkListItem</lookup>
          </lookup>
        </binding>
      </object>
    </property>
  </template>
</interface>

Move this block in the __init__ instead of having it in the global class definition:

Of course, turn the selection, factory, and model into self.selection, self.factory, and self.model.

1 Like

EDIT : OK, I wasn’t using the right gresource prefix ; now I think I’m really close, only a type error in the listItem definition:

self.factory = Gtk.BuilderListItemFactory.new_from_resource(None, '/org/yphil/matinee/listitem.ui')

lv = Gtk.ListView.new(self.selection, self.factory)
self.scrolledWindow.set_child(lv)

(matinee:2): Gtk-CRITICAL **: 01:05:49.447: Error building template for list item: .:0:0 Invalid type 'ModelObject' (3 times)

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <template class="GtkListItem">
    <property name="child">
      <object class="GtkLabel">
        <property name="xalign">0</property>
        <binding name="label">
          <lookup name="name" type="ModelObject">
            <lookup name="item">GtkListItem</lookup>
          </lookup>
        </binding>
      </object>
    </property>
  </template>
</interface>

What should I use for the “type” value?

This blog post says:

"Remember that the classname (GtkListItem) in a ui template is used as the “this” pointer referring to the object that is being instantiated.

So, <lookup name=”item”>GtkListItem</lookup> means: the value of the “item” property of the list item that is created. <lookup name=”string”> means: the “string” property of that object. And <binding name=”label”> says to set the “label” property of the widget to the value of that property."

So I obeyed:

        <binding name="label">
          <lookup name="string">
            <lookup name="item">GtkListItem</lookup>
          </lookup>
        </binding>

But got another

(matinee:2): Gtk-CRITICAL **: 01:19:01.301: Error building template for list item: .:0:0: Type GObject does not have a property name string

And if I try type="gchararray" I get a “Type gchararray does not support properties” :frowning:

The worst is that I have a listView that has been working for weeks now, but it’s using the deprecated TreeView model, and I really want to do things the right way. It’s been days now, and each time I think I understand how it works, it somehow gets away.

You need a GTypeName for your class, so you’ll have to register one with __gtype_name__ = 'ModelObject', otherwise Python might just be generating a GTypeName with some mangling.

Your ModelObject class doesn’t have a property named string, it has a property named name.

1 Like