如何使用GTK4的ColumnView实现类TreeView的树形表格UI
GTK4 ColumnView 实现树形表格UI的最简方案
GTK4 中可通过 Gtk.TreeListModel 配合 ColumnView 实现树形结构的表格,无需拆分控件组合。核心思路是将普通列表模型包装为树形模型,再为 ColumnView 定义多列展示逻辑,以下是最简实现代码(基于 PyGObject):
import gi gi.require_version('Gtk', '4.0') from gi.repository import Gtk, Gio, GObject class TreeColumnViewWindow(Gtk.ApplicationWindow): def __init__(self, app): super().__init__(application=app, title="树形表格示例") self.set_default_size(600, 400) # 构造树形数据结构 def build_tree_data(): return [ { "name": "文档", "size": "2.3 GB", "type": "文件夹", "children": [ {"name": "工作笔记.md", "size": "12 KB", "type": "Markdown 文件"}, {"name": "项目方案.pdf", "size": "1.2 MB", "type": "PDF 文件"}, ] }, { "name": "图片", "size": "1.5 GB", "type": "文件夹", "children": [ { "name": "旅行", "size": "800 MB", "type": "文件夹", "children": [ {"name": "雪山.jpg", "size": "5 MB", "type": "JPEG 图片"}, {"name": "海滩.png", "size": "3 MB", "type": "PNG 图片"}, ] }, {"name": "头像.svg", "size": "10 KB", "type": "SVG 图片"}, ] } ] # 创建基础列表存储 base_store = Gio.ListStore.new(GObject.TYPE_PYOBJECT) for item in build_tree_data(): base_store.append(item) # 定义子节点获取逻辑,包装为树形模型 def fetch_children(node): if "children" in node and node["children"]: child_store = Gio.ListStore.new(GObject.TYPE_PYOBJECT) for child in node["children"]: child_store.append(child) return child_store return None tree_model = Gtk.TreeListModel.new(base_store, False, True, fetch_children) # 创建ColumnView容器 column_view = Gtk.ColumnView(model=tree_model) column_view.set_show_separators(True) # 名称列(带展开/折叠指示器) name_factory = Gtk.SignalListItemFactory() def setup_name_item(factory, list_item): box = Gtk.Box(spacing=6) box.set_halign(Gtk.Align.START) expander = Gtk.TreeExpander() label = Gtk.Label(halign=Gtk.Align.START) box.append(expander) box.append(label) list_item.set_child(box) def bind_name_item(factory, list_item): tree_item = list_item.get_item() if not tree_item: return box = list_item.get_child() expander = box.get_first_child() label = box.get_last_child() expander.set_list_item(list_item) data = tree_item.get_item() label.set_text(data["name"]) name_factory.connect("setup", setup_name_item) name_factory.connect("bind", bind_name_item) name_column = Gtk.ColumnViewColumn(title="名称", factory=name_factory) name_column.set_expand(True) column_view.append_column(name_column) # 通用文本列创建函数(大小、类型列) def create_text_column(title, data_key): factory = Gtk.SignalListItemFactory() def setup_text_item(factory, list_item): label = Gtk.Label(halign=Gtk.Align.END) list_item.set_child(label) def bind_text_item(factory, list_item): tree_item = list_item.get_item() if tree_item: data = tree_item.get_item() list_item.get_child().set_text(data[data_key]) factory.connect("setup", setup_text_item) factory.connect("bind", bind_text_item) return Gtk.ColumnViewColumn(title=title, factory=factory) column_view.append_column(create_text_column("大小", "size")) column_view.append_column(create_text_column("类型", "type")) # 滚动容器包裹ColumnView scrolled_win = Gtk.ScrolledWindow() scrolled_win.set_child(column_view) self.set_child(scrolled_win) class TreeColumnViewApp(Gtk.Application): def __init__(self): super().__init__(application_id="org.example.TreeColumnViewDemo") def do_activate(self): win = TreeColumnViewWindow(self) win.present() if __name__ == "__main__": app = TreeColumnViewApp() app.run(None)
核心实现要点
Gtk.TreeListModel:将普通列表模型转换为树形模型,通过自定义的fetch_children函数指定节点的子项获取逻辑Gtk.TreeExpander:在名称列中添加展开/折叠指示器,实现树形层级的交互- 多列定义:通过
SignalListItemFactory为不同列绑定对应的数据字段,实现表格式展示
内容的提问来源于stack exchange,提问作者Damn Vegetables
相关产品推荐
相关产品推荐

