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

GTK:带ComboBox的TreeView如何为每行设置不同可选项?

为TreeView每行设置不同选项的ComboBox(C语言示例)

要实现每行ComboBox拥有独立可选项,核心是不为CellRendererCombo设置全局模型,而是在TreeView的数据源中新增一列,存储每行对应的ComboBox选项模型,再通过属性绑定将renderer与该行的模型关联。以下是完整实现示例:

完整代码

#include <gtk/gtk.h>

// 定义TreeView的列枚举
typedef enum {
    COLUMN_SELECTED_TEXT,  // 存储ComboBox选中的文本
    COLUMN_COMBO_MODEL,    // 存储每行对应的ComboBox选项模型
    N_COLUMNS
} TreeColumns;

// 销毁ComboBox模型的回调,避免内存泄漏
void on_combo_model_destroy(GtkTreeModel *model, gpointer user_data) {
    g_object_unref(model);
}

int main(int argc, char *argv[]) {
    gtk_init(&argc, &argv);

    // 创建主窗口
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "TreeView with Per-Row Combos");
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    // 创建TreeView及其数据源
    GtkWidget *treeview = gtk_tree_view_new();
    GtkListStore *tree_store = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_OBJECT);
    gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(tree_store));
    g_object_unref(tree_store); // TreeView会持有模型引用,这里可以提前unref

    // 创建ComboBox单元格渲染器
    GtkCellRenderer *combo_renderer = gtk_cell_renderer_combo_new();
    g_object_set(combo_renderer, 
                 "has-entry", FALSE, 
                 "editable", TRUE, 
                 "text-column", 0,  // 每个ComboBox模型的文本列索引
                 NULL);

    // 创建TreeView列,绑定renderer的属性到TreeStore的对应列
    GtkTreeViewColumn *combo_column = gtk_tree_view_column_new_with_attributes(
        "自定义选项",
        combo_renderer,
        "text", COLUMN_SELECTED_TEXT,  // 绑定选中的文本
        "model", COLUMN_COMBO_MODEL,   // 绑定每行的ComboBox模型
        NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), combo_column);

    // -------------------------- 添加示例数据 --------------------------
    // 第一行的ComboBox选项:item1, item2
    GtkListStore *combo_model1 = gtk_list_store_new(1, G_TYPE_STRING);
    gtk_list_store_insert_with_values(combo_model1, NULL, -1, 0, "item1", -1);
    gtk_list_store_insert_with_values(combo_model1, NULL, -1, 0, "item2", -1);
    g_signal_connect(combo_model1, "destroy", G_CALLBACK(on_combo_model_destroy), NULL);
    gtk_list_store_insert_with_values(tree_store, NULL, -1,
                                      COLUMN_SELECTED_TEXT, "item1",
                                      COLUMN_COMBO_MODEL, combo_model1,
                                      -1);
    g_object_unref(combo_model1); // TreeStore会持有引用,这里unref

    // 第二行的ComboBox选项:item3, item4, item5
    GtkListStore *combo_model2 = gtk_list_store_new(1, G_TYPE_STRING);
    gtk_list_store_insert_with_values(combo_model2, NULL, -1, 0, "item3", -1);
    gtk_list_store_insert_with_values(combo_model2, NULL, -1, 0, "item4", -1);
    gtk_list_store_insert_with_values(combo_model2, NULL, -1, 0, "item5", -1);
    g_signal_connect(combo_model2, "destroy", G_CALLBACK(on_combo_model_destroy), NULL);
    gtk_list_store_insert_with_values(tree_store, NULL, -1,
                                      COLUMN_SELECTED_TEXT, "item3",
                                      COLUMN_COMBO_MODEL, combo_model2,
                                      -1);
    g_object_unref(combo_model2);

    // 第三行的ComboBox选项:item6, item7
    GtkListStore *combo_model3 = gtk_list_store_new(1, G_TYPE_STRING);
    gtk_list_store_insert_with_values(combo_model3, NULL, -1, 0, "item6", -1);
    gtk_list_store_insert_with_values(combo_model3, NULL, -1, 0, "item7", -1);
    g_signal_connect(combo_model3, "destroy", G_CALLBACK(on_combo_model_destroy), NULL);
    gtk_list_store_insert_with_values(tree_store, NULL, -1,
                                      COLUMN_SELECTED_TEXT, "item6",
                                      COLUMN_COMBO_MODEL, combo_model3,
                                      -1);
    g_object_unref(combo_model3);
    // -----------------------------------------------------------------

    // 将TreeView放入窗口
    GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_container_add(GTK_CONTAINER(scrolled_window), treeview);
    gtk_container_add(GTK_CONTAINER(window), scrolled_window);

    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}

关键说明

  1. 扩展TreeView数据源:新增COLUMN_COMBO_MODEL列,类型为G_TYPE_OBJECT,用于存储每行独立的GtkListStore(ComboBox的选项模型)。
  2. 独立模型创建:为每行创建专属的GtkListStore,添加不同的选项,并通过gtk_list_store_insert_with_values将模型存入TreeView的数据源。
  3. 属性绑定:通过gtk_tree_view_column_new_with_attributes将CellRendererCombo的model属性绑定到COLUMN_COMBO_MODEL,text属性绑定到COLUMN_SELECTED_TEXT(存储选中的文本)。
  4. 内存管理:为每个ComboBox模型绑定destroy信号,在模型被销毁时自动unref,避免内存泄漏;同时注意TreeView和TreeStore对模型的引用处理。

编译命令(假设文件名是treeview_combo_per_row.c):

gcc treeview_combo_per_row.c -o treeview_combo_per_row `pkg-config --cflags --libs gtk+-3.0`

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:10:28