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; }
关键说明
- 扩展TreeView数据源:新增
COLUMN_COMBO_MODEL列,类型为G_TYPE_OBJECT,用于存储每行独立的GtkListStore(ComboBox的选项模型)。 - 独立模型创建:为每行创建专属的
GtkListStore,添加不同的选项,并通过gtk_list_store_insert_with_values将模型存入TreeView的数据源。 - 属性绑定:通过
gtk_tree_view_column_new_with_attributes将CellRendererCombo的model属性绑定到COLUMN_COMBO_MODEL,text属性绑定到COLUMN_SELECTED_TEXT(存储选中的文本)。 - 内存管理:为每个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
相关产品推荐
相关产品推荐

