I want to manipulate the content of a selected item of a gridview

    def factory_setup(self, fact, item):
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        image = Gtk.Image.new ()
        image.set_pixel_size (180)
        box.append(image)
        label = Gtk.Label()
        label.set_name("LabelTitle")
        label.set_justify(Gtk.Justification.CENTER)
        label.set_wrap(True)
        label.set_natural_wrap_mode(Gtk.NaturalWrapMode.WORD)
        label.set_width_chars(20)
        label.set_ellipsize(Pango.EllipsizeMode.END)
        label.set_size_request(200, -1)
        box.append(label)
        item.set_child (box)

    def on_selected_item(self, selection, position, n_items):
        glist = selection.get_model()
        item = glist.get_item(position)
        box = item.get_item()
        image = box.observe_children()[0]
        image.set_visible(False)

AttributeError: ‘ItemGioListStore’ object has no attribute ‘get_item’. Did you mean: ‘id_item’?

I wanted to hide the image and leave the label when I click on an item

As you did not post the GridView creation code, it is not possible to know how it was created and what type of selection was used, so I will assume that you created the Gtk.GridView, the Gio.ListStore and Gtk.SingleSelection and assigned the model correctly. Furthermore, you also connected the “selection-changed” signal to your on_selected_item function.

In this case the problem is here:

glist = selection.get_model()

selection.get_model() does not return the model but rather a list of models. Probably something like this should work:

glist = selection.get_model()[0]
1 Like
        scroll = Gtk.ScrolledWindow()
        self.gridview = Gtk.GridView()
        scroll.set_child(self.gridview)
        scroll.set_vexpand(True)
        #------------------------------------------
        self.single_selection = Gtk.SingleSelection()
        self.single_selection.set_autoselect(True)
        #------------------------------------------
        self.factory = Gtk.SignalListItemFactory()
        self.factory.connect("setup", self.factory_setup)
        self.factory.connect("bind", self.factory_bind)
        #------------------------------------------
        self.gridview.set_factory(self.factory)
        self.gridview.set_model(self.single_selection)
        #--------------------------------------------
        self.single_selection.connect("selection-changed", self.on_selected_item)

Thanks for attention
But it didn’t work either

Sorry, but you need a Gio.Listore to add the items, and you need to assign it as a model to the selection, among other things.

Now I understand what you are trying to do: you were trying to use GtK.SingleSelection to manipulate the widget that represents the list item in the gridview. This doesn’t work because the item that GtK.SingleSelection refers to is actually the data object contained in the Gio.ListStore, not the widget that visually represents that data object in the grid view

I think I’d better share a full example just in case. The following example does what you want: manipulates the visibility of the box inside the widget that represents the ListStore item in the gridview. How this manipulation will happen depends on how you adapt this example. Note that to achieve this I had to create a reference to the widget that represents the ListStore item in the gridview within the data object that will be contained by the LisStore.

import gi

gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, GObject, Pango, Gio, Gdk        

class DataObject(GObject.GObject):
    def __init__(self, txt: str):
        super(DataObject, self).__init__()
        self.data = txt
        self.widget = None

def setup(widget, item):
    """Setup the widget to show in the Gtk.Listview"""
    box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
    
    texture = Gdk.Texture.new_from_filename("exemple.jpg")    
    image = Gtk.Image.new_from_paintable(texture)
    image.set_pixel_size (180)
   
    box.append(image)
    label = Gtk.Label()
    label.set_name("LabelTitle")
    label.set_text("test")
    label.set_justify(Gtk.Justification.CENTER)
    label.set_wrap(True)
    label.set_natural_wrap_mode(Gtk.NaturalWrapMode.WORD)
    label.set_width_chars(20)
    label.set_ellipsize(Pango.EllipsizeMode.END)
    label.set_size_request(200, -1)
    box.append(label)
    item.set_child (box)


def bind(widget, item):
    """bind data from the store object to the widget"""
    box = item.get_child()
    obj = item.get_item()
    obj.widget = box

def on_selected_item(selection, position, n_items):        
        item = selection.get_selected_item()    
        box = item.widget
        image = box.observe_children()[0]
        image.set_visible(False)

def on_activate(app):
    win = Gtk.ApplicationWindow(
        application=app,
        title="Gtk4 is Awesome !!!",
        default_height=400,
        default_width=400,
    )
    sw = Gtk.ScrolledWindow()

    grid_view = Gtk.GridView()
    factory = Gtk.SignalListItemFactory()
    factory.connect("setup", setup)
    factory.connect("bind", bind)
    grid_view.set_factory(factory)

    store = Gio.ListStore.new(DataObject)

    selection = Gtk.SingleSelection()
    
    selection.connect("selection-changed", on_selected_item)
        
    selection.set_model(store)

    grid_view.set_model(selection)

    v1 = DataObject("entrada 01")
    v2 = DataObject("entrada 02")
    store.append(v1)
    store.append(v2)

    sw.set_child(grid_view)
    win.set_child(sw)
    win.present()


app = Gtk.Application(application_id="org.gtk.Example")
app.connect("activate", on_activate)
app.run(None)
1 Like

I would recommend, instead of keeping a backreference to the widget and violating the model/view split, to instead add properties to the row object type inside the store and bind those properties to the “visible” property of the widget.

In general, you want a clear separation between row objects and row widgets: the row object owns and controls the state, and the row widget responds to state changes.

Thanks, it’s a smart move