gtk2.0怎样使用列表控件实现反复填充

⌚Time: 2025-04-08 16:21:00

👨‍💻Author: Jack Ge

下面是deepseek给的代码


#include <gtk/gtk.h>

enum {
    COL_NAME,
    COL_AGE,
    COL_CITY,
    NUM_COLS
};

GtkListStore *list_store;
GtkWidget *tree_view;

static GtkWidget* create_view_and_model(void) {
    GtkTreeViewColumn *col;
    GtkCellRenderer *renderer;
    
    // 创建列表存储
    list_store = gtk_list_store_new(NUM_COLS, 
                                  G_TYPE_STRING,
                                  G_TYPE_INT,
                                  G_TYPE_STRING);
    
    // 创建TreeView
    tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
    
    // 添加姓名列
    renderer = gtk_cell_renderer_text_new();
    col = gtk_tree_view_column_new_with_attributes("name",
                                                  renderer,
                                                  "text", COL_NAME,
                                                  NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), col);
    
    // 添加年龄列
    renderer = gtk_cell_renderer_text_new();
    col = gtk_tree_view_column_new_with_attributes("age",
                                                  renderer,
                                                  "text", COL_AGE,
                                                  NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), col);
    
    // 添加城市列
    renderer = gtk_cell_renderer_text_new();
    col = gtk_tree_view_column_new_with_attributes("city",
                                                  renderer,
                                                  "text", COL_CITY,
                                                  NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), col);
    
    return tree_view;
}

void on_clear_clicked(GtkButton *button, gpointer user_data) {
    gtk_list_store_clear(list_store);
    g_print("list cleared\n");
}

void on_refill_clicked(GtkButton *button, gpointer user_data) {
    GtkTreeIter iter;
    
    // 清空现有数据
    gtk_list_store_clear(list_store);
    
    // 添加新数据
    gtk_list_store_append(list_store, &iter);
    gtk_list_store_set(list_store, &iter,
                      COL_NAME, "new zhasngsan",
                      COL_AGE, 27,
                      COL_CITY, "new beijing",
                      -1);
    
    gtk_list_store_append(list_store, &iter);
    gtk_list_store_set(list_store, &iter,
                      COL_NAME, "new lisi",
                      COL_AGE, 32,
                      COL_CITY, "new shanghai",
                      -1);
    
    gtk_list_store_append(list_store, &iter);
    gtk_list_store_set(list_store, &iter,
                      COL_NAME, "new wangwu",
                      COL_AGE, 29,
                      COL_CITY, "new guangzhou",
                      -1);
    
    g_print("list refill\n");
}

int main(int argc, char **argv) {
    GtkWidget *window;
    GtkWidget *view;
    GtkWidget *vbox;
    GtkWidget *hbox;
    GtkWidget *clear_btn;
    GtkWidget *refill_btn;
    
    gtk_init(&argc, &argv);
    
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_window_set_title(GTK_WINDOW(window), "demo");
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
    
    vbox = gtk_vbox_new(FALSE, 5);
    gtk_container_add(GTK_CONTAINER(window), vbox);
    
    // 创建TreeView
    view = create_view_and_model();
    gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);
    
    // 创建按钮栏
    hbox = gtk_hbox_new(TRUE, 5);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
    
    // 清空按钮
    clear_btn = gtk_button_new_with_label("clear list");
    g_signal_connect(clear_btn, "clicked", G_CALLBACK(on_clear_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox), clear_btn, TRUE, TRUE, 0);
    
    // 重新填充按钮
    refill_btn = gtk_button_new_with_label("refill");
    g_signal_connect(refill_btn, "clicked", G_CALLBACK(on_refill_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox), refill_btn, TRUE, TRUE, 0);
    
    gtk_widget_show_all(window);
    gtk_main();
    
    return 0;
}

理解:

GTK2.0的列表控件使用的MVC模式,也就是数据-视图-控制独立的办法。gtk_list_store_new是创建数据储存实体,gtk_tree_view_new_with_model是使用创建的数据储存模型创建视图,gtk_tree_view_column_new_with_attributes是为视图创建新列以对应数据储存模型,里面的列数据。

当需要填充数据时先用gtk_list_store_clear清除数据储存模型,之后再重新填充。

运行测试

在大量更新数据时,可以使用gtk_tree_view_set_model(NULL) 暂时解除模型关联,操作完成后再重新关联。这样可以避免在数据更新过程中用户看到列表内容不断变化,保持界面稳定性,直到所有更新完成。

但是如果需要完全释放模型,需要显式调用 g_object_unref()。