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

GTK3:点击按钮时保存TreeView中未完成的编辑内容

GTK3 TreeView 保存未完成编辑数据的解决方案

核心思路

点击保存按钮时,需要强制TreeView结束当前的单元格编辑会话,将编辑缓冲区中的未提交数据同步到ListStore,之后再执行保存逻辑即可。

针对你的疑问逐一解答

  • 是否需要为CellRenderer添加Gtk.Entry?
    不需要。默认的CellRendererText在编辑状态下会自动创建临时的Gtk.Entry用于输入,无需手动添加。

  • 是否要设置其他CellRenderer属性?
    除了editable=true,可以显式设置mode为CELL_RENDERER_MODE_EDITABLE(默认就是这个值,显式设置可避免潜在问题)。如果使用默认的CellRendererText,其他默认属性足够满足需求,无需额外配置。

  • 实现方式选择
    推荐在保存按钮的回调中处理,逻辑更直接:

    1. 调用treeview.EndEditing(true)强制结束当前所有编辑会话,将缓冲区数据提交到ListStore;
    2. 遍历ListStore读取最新数据,执行保存操作。

    也可以通过CellRenderer的editing-started回调记录当前编辑的Entry实例,保存时直接从Entry的缓冲区取数据写入ListStore,但这种方式需要维护额外状态,不如前者简洁。

  • 关于编辑缓冲区
    当单元格处于编辑状态时,临时Entry的Gtk.EntryBuffer确实会暂存未提交的数据,调用EndEditing后,缓冲区内容会触发CellRenderer的edited回调,自动同步到ListStore的对应列。


Go语言示例(基于gotk3库)

package main

import (
    "fmt"
    "github.com/gotk3/gotk3/gtk"
    "os"
)

func main() {
    gtk.Init(&os.Args)

    // 创建主窗口
    win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
    win.SetTitle("TreeView 保存示例")
    win.Connect("destroy", gtk.MainQuit)
    win.SetDefaultSize(400, 300)

    // 创建ListStore模型:两列(ID字符串、值字符串)
    listStore, _ := gtk.ListStoreNew(gtk.TYPE_STRING, gtk.TYPE_STRING)
    // 插入测试数据
    addRow(listStore, "1", "初始值1")
    addRow(listStore, "2", "初始值2")

    // 创建TreeView并绑定模型
    treeView, _ := gtk.TreeViewNewWithModel(listStore)
    treeView.SetHeadersVisible(true)

    // 添加ID列(不可编辑)
    idRenderer, _ := gtk.CellRendererTextNew()
    idColumn, _ := gtk.TreeViewColumnNewWithAttribute("ID", idRenderer, "text", 0)
    treeView.AppendColumn(idColumn)

    // 添加可编辑的值列
    valueRenderer, _ := gtk.CellRendererTextNew()
    valueRenderer.SetProperty("editable", true)
    // 编辑完成时自动更新ListStore
    valueRenderer.Connect("edited", func(r *gtk.CellRendererText, path string, newText string) {
        iter, _ := listStore.GetIterFromString(path)
        listStore.Set(iter, []int{1}, []interface{}{newText})
    })
    valueColumn, _ := gtk.TreeViewColumnNewWithAttribute("值", valueRenderer, "text", 1)
    treeView.AppendColumn(valueColumn)

    // 创建保存按钮
    saveBtn, _ := gtk.ButtonNewWithLabel("保存")
    saveBtn.Connect("clicked", func() {
        // 关键操作:结束所有未完成的编辑,提交数据到ListStore
        treeView.EndEditing(true)

        // 遍历ListStore,执行保存逻辑
        fmt.Println("===== 保存的数据 =====")
        iter, valid := listStore.GetIterFirst()
        for valid {
            idVal, _ := listStore.GetValue(iter, 0)
            valueVal, _ := listStore.GetValue(iter, 1)
            fmt.Printf("ID: %s | 值: %s\n", idVal, valueVal)
            // 此处替换为实际保存逻辑(写入文件/数据库等)
            valid = listStore.IterNext(iter)
        }
    })

    // 布局组装
    vbox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5)
    vbox.PackStart(treeView, true, true, 0)
    vbox.PackStart(saveBtn, false, false, 5)
    win.Add(vbox)

    win.ShowAll()
    gtk.Main()
}

// 辅助函数:向ListStore添加一行数据
func addRow(store *gtk.ListStore, id, value string) {
    iter := store.Append()
    store.Set(iter, []int{0, 1}, []interface{}{id, value})
}

其他语言思路(以C为例)

在保存按钮的回调函数中执行:

// 结束当前编辑会话
gtk_tree_view_end_editing(GTK_TREE_VIEW(tree_view), TRUE);

// 遍历TreeModel读取最新数据
GtkTreeIter iter;
gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list_store), &iter);
while (valid) {
    gchar *id, *value;
    gtk_tree_model_get(GTK_TREE_MODEL(list_store), &iter, 0, &id, 1, &value, -1);
    // 执行保存操作
    g_print("ID: %s, 值: %s\n", id, value);
    g_free(id);
    g_free(value);
    valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store), &iter);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 22:53:11