You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GTK4(≥4.10)中构建类TreeView的树形组件?

用GTK4的ColumnView + TreeExpander实现树形结构(替代废弃的TreeView)

GTK4.10+废弃TreeView后,官方推荐用ColumnView + TreeExpander + TreeListModel的组合实现树形结构,核心逻辑是用TreeListModel把树形数据源转换成ColumnView能识别的扁平列表,再通过TreeExpander处理节点的展开/折叠交互。

核心组件作用

  • TreeListModel:将嵌套的树形数据包装成ColumnView可直接使用的扁平Gio.ListModel,自动管理节点的展开/折叠状态。
  • TreeExpander:作为ColumnView的单元格组件,负责显示展开/折叠箭头,并关联TreeListModel的节点数据。
  • ColumnView:负责列布局,将TreeExpander放在首列实现树形缩进,其他列展示业务数据。

完整示例(PyGObject)

下面是一个可运行的Python示例,实现多级树形结构:

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio

# 自定义树形数据类(PyGObject中可直接用普通类,C语言需实现GObject子类)
class TreeNode:
    def __init__(self, name, children=None):
        self.name = name
        self.children = children or []

# 生成子节点ListModel的回调函数
def create_child_model(item):
    child_store = Gio.ListStore.new(TreeNode)
    for child in item.children:
        child_store.append(child)
    return child_store

def on_app_activate(app):
    # 创建主窗口
    window = Gtk.ApplicationWindow(application=app, title="树形ColumnView示例")
    window.set_default_size(450, 600)

    # 构建树形数据源
    root_node = TreeNode("根目录", [
        TreeNode("文档", [
            TreeNode("工作文档"),
            TreeNode("个人笔记", [
                TreeNode("旅行计划"),
                TreeNode("技术总结")
            ])
        ]),
        TreeNode("图片", [
            TreeNode("风景照"),
            TreeNode("截图")
        ]),
        TreeNode("下载")
    ])

    # 创建根节点的ListModel
    root_store = Gio.ListStore.new(TreeNode)
    root_store.append(root_node)

    # 初始化TreeListModel:参数依次为根model、是否透传顶层节点、是否自动展开
    tree_list_model = Gtk.TreeListModel.new(root_store, False, False, create_child_model)

    # 创建ColumnView
    column_view = Gtk.ColumnView(model=tree_list_model)
    column_view.set_show_column_separators(True)

    # 第一列:树形展开列
    expander_column = Gtk.ColumnViewColumn(title="名称")
    expander_factory = Gtk.SignalListItemFactory()

    # 初始化单元格UI
    def setup_expander(_, list_item):
        expander = Gtk.TreeExpander()
        label = Gtk.Label(xalign=0)  # 左对齐
        expander.set_child(label)
        list_item.set_child(expander)

    # 绑定数据到单元格
    def bind_expander(_, list_item):
        expander = list_item.get_child()
        label = expander.get_child()
        # 获取TreeListModel的包装节点
        tree_item = list_item.get_item()
        # 绑定TreeExpander到ListItem,让它自动处理展开状态
        expander.set_list_item(list_item)
        # 获取实际业务数据
        node = tree_item.get_item()
        label.set_label(node.name)

    expander_factory.connect("setup", setup_expander)
    expander_factory.connect("bind", bind_expander)
    expander_column.set_factory(expander_factory)
    column_view.append_column(expander_column)

    # 第二列:示例附加信息列
    info_column = Gtk.ColumnViewColumn(title="类型")
    info_factory = Gtk.SignalListItemFactory()

    def setup_info(_, list_item):
        label = Gtk.Label(xalign=0)
        list_item.set_child(label)

    def bind_info(_, list_item):
        label = list_item.get_child()
        tree_item = list_item.get_item()
        node = tree_item.get_item()
        label.set_label("目录" if node.children else "文件")

    info_factory.connect("setup", setup_info)
    info_factory.connect("bind", bind_info)
    info_column.set_factory(info_factory)
    column_view.append_column(info_column)

    # 将ColumnView放入滚动窗口
    scrolled_window = Gtk.ScrolledWindow()
    scrolled_window.set_child(column_view)
    window.set_child(scrolled_window)

    window.present()

if __name__ == "__main__":
    app = Gtk.Application(application_id="com.example.TreeColumnViewDemo")
    app.connect("activate", on_app_activate)
    app.run(None)

关键细节说明

  1. TreeListModel初始化参数:
    • 第二个参数passthrough:设为False时,顶层节点会被包装成Gtk.TreeListItem;设为True则直接透传原始数据(适合顶层是多个根节点的场景)。
    • 第三个参数autoexpand:设为True会默认展开所有节点,False则默认折叠。
  2. TreeExpander绑定:必须调用set_list_item()将其关联到ColumnView的ListItem,否则无法识别节点的展开状态和子节点。
  3. 数据绑定逻辑:通过Gtk.TreeListItem.get_item()获取原始业务数据,再将数据渲染到UI组件上。
  4. C语言适配:逻辑完全一致,需将自定义数据实现为GObject子类,并实现GtkTreeListModelCreateModelFunc回调函数返回子节点的GListModel。

内容的提问来源于stack exchange,提问作者Dorbmon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 17:01:09