GTK4构建列表GtkListView最佳实践

xingyun86 19天前 88

GTK4构建列表GtkListView最佳实践

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

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

#define ELEM_NUM 2
static void
setup_listitem_cb(GtkListItemFactory* factory,
    GtkListItem* list_item)
{
    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
bind_listitem_cb(GtkListItemFactory* factory,
    GtkListItem* list_item)
{
    GtkWidget* box = gtk_list_item_get_child(list_item);
    GtkStringList* stringlist = GTK_STRING_LIST(gtk_list_item_get_item(list_item));
    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_list_item_double_click(GtkGestureClick* gesture, gint n_press, gdouble x, gdouble y, gpointer user_data)
{
    if (n_press == 2) {
        GtkListView* listview = GTK_LIST_VIEW(user_data);
        //单选/多选通用方法
        GtkSelectionModel* selectionmodel = gtk_list_view_get_model(listview);
        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);
                GtkStringList* stringlist = GTK_STRING_LIST(g_list_model_get_object(G_LIST_MODEL(selectionmodel), value));
                for (int i = 0; i < ELEM_NUM; i++)
                {
                    g_print("%s\n", gtk_string_list_get_string(stringlist, i));
                }
            }
        }
        //若单选可如此
        GtkStringList* stringlist = GTK_STRING_LIST(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++)
        {
            g_print("%s\n", gtk_string_list_get_string(stringlist, i));
        }
        {
            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] = {
                {G_UTF8("ccc"),G_UTF8("ddd"),},
                {G_UTF8("ddd"),G_UTF8("eee"),},
            };
            int n = sizeof(listdata) / sizeof(*listdata);
            for (int i = 0; i < n; i++)
            {
                printf("%d,%s,%s\n", i, listdata[i][0], listdata[i][1]);
                GtkStringList* stringlist = gtk_string_list_new(listdata[i]);
                //GtkStringList* stringlist = gtk_string_list_new(NULL);
                //for (int j = 0; j < ELEM_NUM; j++)
                //{
                //    gtk_string_list_append(stringlist, listdata[i][j]);
                //}
                g_list_store_append(liststore, stringlist);
            }
            g_list_model_items_changed(G_LIST_MODEL(liststore), n_old - 1, 0, 0);
        }
    }
}
...
GtkWidget* win = gtk_window_new();
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] = {
    {G_UTF8("aaa"),G_UTF8("bbb"),},
    {G_UTF8("bbb"),G_UTF8("ccc"),},
};
int n = sizeof(listdata) / sizeof(*listdata);
printf("n=%d\n", n);
for (int i = 0; i < n; i++)
{
    printf("%d,%s,%s\n", i, listdata[i][0], listdata[i][1]);
    GtkStringList* stringlist = gtk_string_list_new(listdata[i]);
    //GtkStringList* stringlist = gtk_string_list_new(NULL);
    //for (int j = 0; j < ELEM_NUM; j++)
    //{
    //    gtk_string_list_append(stringlist, listdata[i][j]);
    //}
    g_list_store_append(liststore, stringlist);
}
GtkSelectionModel* selectionmodel = GTK_SELECTION_MODEL(gtk_single_selection_new(G_LIST_MODEL(liststore)));
GtkListItemFactory* factory = gtk_signal_list_item_factory_new();
g_signal_connect(factory, "setup", G_CALLBACK(setup_listitem_cb), NULL);
g_signal_connect(factory, "bind", G_CALLBACK(bind_listitem_cb), NULL);
GtkWidget* listview = gtk_list_view_new(selectionmodel, factory);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolledwindow), listview);
GtkGesture* gesture = gtk_gesture_click_new();
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), GDK_BUTTON_PRIMARY);
gtk_widget_add_controller(listview, GTK_EVENT_CONTROLLER(gesture));
g_signal_connect(gesture, "pressed", G_CALLBACK(on_list_item_double_click), listview);
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++)
    {
        printf("%d,%s,%s\n", i, listdata[i][0], listdata[i][1]);
        GtkStringList* stringlist = gtk_string_list_new(listdata[i]);
        //GtkStringList* stringlist = gtk_string_list_new(NULL);
        //for (int j = 0; j < ELEM_NUM; j++)
        //{
        //    gtk_string_list_append(stringlist, listdata[i][j]);
        //}
        g_list_store_append(liststore, stringlist);
    }
    g_list_model_items_changed(G_LIST_MODEL(liststore), n_old - 1, 0, 0);
}
...


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