GTK4使用GtkColumnView最佳实践

xingyun86 5月前 652

GTK4使用GtkColumnView最佳实践

gtk4丢弃很多gtk3的类,GtkColumnView是新版本的其中之一,今天就用GtkColumnView实现常用的操作。

以下示例代码实现了动态增加列表数据,一行用多个控件,双击响应事件,以及单选和多选处理逻辑

#define ELEM_NUM 2
#define G_UTF8(s) g_locale_to_utf8(s, -1, 0, 0, 0)
static void
columnview_setup_listitem_cb(GtkListItemFactory* factory,
    GtkListItem* list_item, gpointer user_data)
{
    int col = (int)user_data;
    printf("columnview_setup_listitem_cb %d\n", col);
    GtkWidget* box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
    for (int i = 0; i < ELEM_NUM; i++)
    {
        GtkWidget* label = gtk_label_new("");
        gtk_box_append(GTK_BOX(box), label);
    }
    gtk_list_item_set_child(list_item, box);
}
static void
columnview_bind_listitem_cb(GtkListItemFactory* factory,
    GtkListItem* list_item, gpointer user_data)
{
    int col = (int)user_data;
    printf("columnview_bind_listitem_cb %d\n", col);
    GtkWidget* box = gtk_list_item_get_child(list_item);
    GListModel* listmodel = G_LIST_MODEL(gtk_list_item_get_item(list_item));
    GtkStringList* stringlist = GTK_STRING_LIST(g_list_model_get_item(listmodel, col));
    GtkWidget* label = gtk_widget_get_first_child(box);
    for (int i = 0; i < ELEM_NUM; i++)
    {
        gtk_label_set_label(GTK_LABEL(label), gtk_string_list_get_string(stringlist, i));
        label = gtk_widget_get_next_sibling(label);
    }
}
static void
on_columnview_list_item_double_click(GtkGestureClick* gesture, gint n_press, gdouble x, gdouble y, gpointer user_data)
{
    if (n_press == 2) {
        GtkColumnView* columnview = GTK_COLUMN_VIEW(user_data);
        //单选/多选通用方法
        GtkSelectionModel* selectionmodel = gtk_column_view_get_model(columnview);
        GtkBitset* selected_items = gtk_selection_model_get_selection(selectionmodel);
        if (selected_items) {
            guint value = 0;
            GtkBitsetIter iter = {};
            for (gboolean b = gtk_bitset_iter_init_first(&iter, selected_items, &value); b == TRUE; b = gtk_bitset_iter_next(&iter, &value))
            {
                value = gtk_bitset_iter_get_value(&iter);
                g_print("Selected item: %u\n", value);
                GListStore* _liststore = G_LIST_STORE(g_list_model_get_object(G_LIST_MODEL(selectionmodel), value));
                for (int i = 0; i < ELEM_NUM; i++)
                {
                    GtkStringList* stringlist = GTK_STRING_LIST(g_list_model_get_item(G_LIST_MODEL(_liststore), i));
                    for (int j = 0; j < ELEM_NUM; j++)
                    {
                        g_print("%s\n", gtk_string_list_get_string(stringlist, j));
                    }
                }
            }
        }
        //若单选可如此
        GListStore* _liststore = G_LIST_STORE(gtk_single_selection_get_selected_item(GTK_SINGLE_SELECTION(selectionmodel)));
        g_print("Double-clicked on item: \n");
        for (int i = 0; i < ELEM_NUM; i++)
        {
            GtkStringList* stringlist = GTK_STRING_LIST(g_list_model_get_item(G_LIST_MODEL(_liststore), i));
            for (int j = 0; j < ELEM_NUM; j++)
            {
                g_print("%s\n", gtk_string_list_get_string(stringlist, j));
            }
        }
        {
            GListStore* liststore = G_LIST_STORE(gtk_single_selection_get_model(GTK_SINGLE_SELECTION(selectionmodel)));
            int n_old = g_list_model_get_n_items(G_LIST_MODEL(liststore));
            const char* listdata[][ELEM_NUM + 1][ELEM_NUM + 1] = {
                {{G_UTF8("ccc"),G_UTF8("ddd"),}, {G_UTF8("ddd"),G_UTF8("eee"),}, {G_UTF8("ddd"),G_UTF8("eee"),}, },
                {{G_UTF8("ccc1"),G_UTF8("ddd1"),}, {G_UTF8("ddd1"),G_UTF8("eee1"),}, {G_UTF8("ddd1"),G_UTF8("eee1"),}, },
            };
            int n = sizeof(listdata) / sizeof(*listdata);
            printf("n_old=%d,%d\n", n_old, n);
            for (int i = 0; i < n; i++)
            {
                GListStore* _liststore = g_list_store_new(G_TYPE_OBJECT);
                for (int j = 0; j < ELEM_NUM + 1; j++)
                {
                    printf("%d,%s,%s\n", i, listdata[i][j][0], listdata[i][j][1]);
                    GtkStringList* stringlist = gtk_string_list_new(listdata[i][j]);
                    //GtkStringList* stringlist = gtk_string_list_new(NULL);
                    //for (int k = 0; k < ELEM_NUM; k++)
                    //{
                    //    gtk_string_list_append(_liststore, listdata[i][j][k]);
                    //}
                    g_list_store_append(_liststore, stringlist);
                }
                g_list_store_append(liststore, _liststore);
            }
            g_list_model_items_changed(G_LIST_MODEL(liststore), n_old - 1, 0, 0);
        }
    }
}
void columnview_test(GtkApplication* app)
{
    GtkWidget* win = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(win), G_UTF8("GTK4列表例子"));
    gtk_window_set_default_size(GTK_WINDOW(win), 800, 600);
    GtkWidget* scrolledwindow = gtk_scrolled_window_new();
    gtk_window_set_child(GTK_WINDOW(win), scrolledwindow);
    GListStore* liststore = g_list_store_new(G_TYPE_OBJECT);
    const char* listdata[][ELEM_NUM + 1][ELEM_NUM + 1] = {
        {{G_UTF8("aaa"),G_UTF8("bbb"),}, {G_UTF8("bbb"),G_UTF8("ccc"),},{G_UTF8("bbb"),G_UTF8("ccc"),},},
        {{G_UTF8("eee"),G_UTF8("fff"),}, {G_UTF8("vvv"),G_UTF8("bbb"),},{G_UTF8("vvv"),G_UTF8("bbb"),},},
    };
    int n = sizeof(listdata) / sizeof(*listdata);
    printf("n=%d\n", n);
    for (int i = 0; i < n; i++)
    {
        GListStore* _liststore = g_list_store_new(G_TYPE_OBJECT);
        for (int j = 0; j < ELEM_NUM + 1; j++)
        {
            printf("%d,%s,%s\n", i, listdata[i][j][0], listdata[i][j][1]);
            GtkStringList* stringlist = gtk_string_list_new(listdata[i][j]);
            //GtkStringList* stringlist = gtk_string_list_new(NULL);
            //for (int k = 0; k < ELEM_NUM; k++)
            //{
            //    gtk_string_list_append(_liststore, listdata[i][j][k]);
            //}
            g_list_store_append(_liststore, stringlist);
        }
        g_list_store_append(liststore, _liststore);
    }
    //GtkTreeSelection;
    GtkSelectionModel* selectionmodel = GTK_SELECTION_MODEL(gtk_single_selection_new(G_LIST_MODEL(liststore)));
    GtkWidget* columnview = gtk_column_view_new(selectionmodel);
    gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolledwindow), columnview);
    const char* column_names[] = { G_UTF8("姓名"),G_UTF8("性别"),G_UTF8("年龄"), };
    for (int i = 0; i < sizeof(column_names) / sizeof(*column_names); i++)
    {
        GtkListItemFactory* factory = gtk_signal_list_item_factory_new();
        g_signal_connect(factory, "setup", G_CALLBACK(columnview_setup_listitem_cb), (gpointer)i);
        g_signal_connect(factory, "bind", G_CALLBACK(columnview_bind_listitem_cb), (gpointer)i);
        GtkColumnViewColumn* columnviewcolumn = gtk_column_view_column_new(column_names[i], factory);
        gtk_column_view_column_set_expand(columnviewcolumn, TRUE);
        gtk_column_view_column_set_resizable(columnviewcolumn, TRUE);
        gtk_column_view_append_column(GTK_COLUMN_VIEW(columnview), columnviewcolumn);
    }
    gtk_column_view_set_show_column_separators(GTK_COLUMN_VIEW(columnview), TRUE);
    gtk_column_view_set_show_row_separators(GTK_COLUMN_VIEW(columnview), TRUE);
    GtkGesture* gesture = gtk_gesture_click_new();
    gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), GDK_BUTTON_PRIMARY);
    gtk_widget_add_controller(columnview, GTK_EVENT_CONTROLLER(gesture));
    g_signal_connect(gesture, "pressed", G_CALLBACK(on_columnview_list_item_double_click), columnview);
    gtk_window_present(GTK_WINDOW(win));
    {
        int n_old = g_list_model_get_n_items(G_LIST_MODEL(liststore));
        printf("n_old=%d,%d\n", n_old, n);
        for (int i = 0; i < n; i++)
        {
            GListStore* _liststore = g_list_store_new(G_TYPE_OBJECT);
            for (int j = 0; j < ELEM_NUM + 1; j++)
            {
                printf("%d,%s,%s\n", i, listdata[i][j][0], listdata[i][j][1]);
                GtkStringList* stringlist = gtk_string_list_new(listdata[i][j]);
                //GtkStringList* stringlist = gtk_string_list_new(NULL);
                //for (int k = 0; k < ELEM_NUM; k++)
                //{
                //    gtk_string_list_append(_liststore, listdata[i][j][k]);
                //}
                g_list_store_append(_liststore, stringlist);
            }
            g_list_store_append(liststore, _liststore);
        }
        g_list_model_items_changed(G_LIST_MODEL(liststore), n_old - 1, 0, 0);
    }
}
static void
activate(GtkApplication* app, gpointer user_data)
{
    columnview_test(app);
    return;
}


×
打赏作者
最新回复 (0)
查看全部
全部楼主
返回