GTK4 ColumnView如何在单个单元格修改时更新整行?
如何让GTK4的ColumnView在单元格修改时实时更新整行显示
当前代码中,修改字符串或ASCII码单元格时,模型数据已经同步更新,但ColumnView只有在切换行时才会刷新显示。要实现无需切换行就实时更新,核心在于让DataObject的属性变更能够通知到Gio.ListStore,进而触发ColumnView的实时刷新。
解决方案
问题出在属性绑定的方向和模型通知机制上:默认的属性绑定只处理单向同步,且当你直接修改DataObject的属性时,需要确保模型能够感知到对象的属性变化并触发视图更新。我们需要做两处关键修改:
- 在
bind_property时添加GObject.BindingFlags.BIDIRECTIONAL,实现双向绑定,确保视图和模型的实时同步。 - 在修改
DataObject的属性后,手动触发Gio.ListStore的items_changed信号,通知视图更新对应行的内容。
修改后的完整代码
import gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, Gio, GObject class DataObject(GObject.GObject): __gtype_name__ = 'DataObject' text = GObject.Property(type=str, default=None) number = GObject.Property(type=str, default=None) def __init__(self, text, number): super().__init__() self.text = text self.number = number def setup_c1(widget, item): """Setup the widget to show in the Gtk.Listview""" cell = Gtk.EditableLabel() item.set_child(cell) cell.connect('changed', on_c1_change, item) def bind_c1(widget, item): """bind data from the store object to the widget""" label = item.get_child() obj = item.get_item() # 添加双向绑定,确保模型变更也能同步回视图 label.bind_property( "text", obj, "text", GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL ) def setup_c2(widget, item): """Setup the widget to show in the Gtk.Listview""" cell = Gtk.EditableLabel() item.set_child(cell) cell.connect('changed', on_c2_change, item) def bind_c2(widget, item): """bind data from the store object to the widget""" label = item.get_child() obj = item.get_item() # 添加双向绑定 label.bind_property( "text", obj, "number", GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL ) def on_c1_change(self, item): obj = item.get_item() obj.number = str(ord(obj.text)) # 获取对象在store中的位置,触发items_changed信号 store = item.get_list_item_factory().get_list_model() idx = store.find(obj) if idx != -1: store.items_changed(idx, 1, 1) def on_c2_change(self, item): obj = item.get_item() if not obj.number == '' and int(obj.number) >= 65: obj.text = chr(int(obj.number)) # 获取对象在store中的位置,触发items_changed信号 store = item.get_list_item_factory().get_list_model() idx = store.find(obj) if idx != -1: store.items_changed(idx, 1, 1) def on_activate(app): win = Gtk.ApplicationWindow( application=app, title="GTK 4 ColumnView实时更新示例", default_height=400, default_width=400, ) list_view = Gtk.ColumnView() factory_c1 = Gtk.SignalListItemFactory() factory_c1.connect("setup", setup_c1) factory_c1.connect("bind", bind_c1) factory_c2 = Gtk.SignalListItemFactory() factory_c2.connect("setup", setup_c2) factory_c2.connect("bind", bind_c2) selection = Gtk.SingleSelection() store = Gio.ListStore.new(DataObject) selection.set_model(store) list_view.set_model(selection) # 给工厂绑定list_model,方便后续获取store factory_c1.set_list_model(store) factory_c2.set_list_model(store) column1 = Gtk.ColumnViewColumn.new("String", factory_c1) column2 = Gtk.ColumnViewColumn.new("ASCII Code", factory_c2) list_view.append_column(column1) list_view.append_column(column2) for i in range(65, 91): store.append(DataObject(chr(i), str(i))) sw = Gtk.ScrolledWindow() sw.set_child(list_view) win.set_child(sw) win.present() app = Gtk.Application(application_id="org.gtk.Example") app.connect("activate", on_activate) app.run(None)
关键修改说明
- 双向属性绑定:在
bind_c1和bind_c2中,添加GObject.BindingFlags.BIDIRECTIONAL,这样当模型的text或number属性变更时,视图的EditableLabel会自动同步更新内容。 - 触发模型更新信号:在
on_c1_change和on_c2_change回调中,通过store.find(obj)找到当前对象在ListStore中的索引,然后调用store.items_changed(idx, 1, 1)通知视图:该位置的1个条目发生了变化,需要重新渲染。 - 绑定ListModel到工厂:通过
factory_c1.set_list_model(store)将ListStore绑定到工厂,方便在回调中直接获取到模型对象,避免额外的传递逻辑。
这样修改后,修改任意一个单元格时,另一列的内容会立即更新,无需切换行。
内容的提问来源于stack exchange,提问作者Mint Julep
相关产品推荐
相关产品推荐

