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:
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)
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.