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

GTK4中ListView显示乱码求助(附代码及Pango警告)

GTK4 ListView 显示乱码问题解决

程序编译无问题,但运行后ListView显示乱码,报错信息如下:

a.out:13295): Pango-WARNING **: 19:22:58.287: Invalid UTF-8 string passed to pango_layout_set_text()

原代码实现

#include <gtk/gtk.h>

static GListModel* create_model()
{

        GListStore *store;
        store = g_list_store_new(G_TYPE_OBJECT);
        g_list_store_append(store, gtk_string_object_new("London"));
        g_list_store_append(store, gtk_string_object_new("Paris"));
        g_list_store_append(store, gtk_string_object_new("Berlin"));

        return G_LIST_MODEL (store);
}

static void setup_list_item_cb (GtkListItemFactory *factory, GtkListItem *list_item)
{
        GtkWidget *label = gtk_label_new (NULL);
        gtk_list_item_set_child (GTK_LIST_ITEM(list_item), label);
}

static void bind_list_item_cb (GtkListItemFactory *factory, GtkListItem  *list_item)
{
        GtkWidget *label = gtk_list_item_get_child (list_item);
        const char *string = gtk_list_item_get_item(list_item);
        gtk_label_set_text (GTK_LABEL (label), string);
}

static void activate (GtkApplication *app, gpointer user_data)
{
        GtkWidget *window; GtkWidget *scrolled_window;
        GtkWidget *list_view;
        GtkListItemFactory *factory;
        GListModel *model;

        model = create_model();
        GtkSingleSelection *selection;
        selection = gtk_single_selection_new(G_LIST_MODEL(model));
        gtk_single_selection_set_autoselect(selection,TRUE);

        window = gtk_application_window_new (app);
        gtk_window_set_title (GTK_WINDOW (window), "ListView Example");
        gtk_window_set_default_size (GTK_WINDOW (window), 300, 200);
        scrolled_window = gtk_scrolled_window_new ();
        gtk_window_set_child (GTK_WINDOW (window), scrolled_window);
                                                                                                                                                                     
        list_view = gtk_list_view_new (GTK_SELECTION_MODEL(selection), factory);
        gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window), list_view);

        factory = gtk_signal_list_item_factory_new ();
        g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item_cb), NULL);
        g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item_cb), NULL);
        gtk_list_view_set_factory (GTK_LIST_VIEW (list_view), factory);
        gtk_window_present (GTK_WINDOW (window));
}

int main (int argc, char **argv)
{
        GtkApplication *app; int status;

        app = gtk_application_new ("org.gtk.listview", G_APPLICATION_DEFAULT_FLAGS);
        g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
        status = g_application_run (G_APPLICATION (app), argc, argv); g_object_unref (app);
        return status;
}

错误原因及修正方案

1. 核心错误:类型转换错误

在bind_list_item_cb中,gtk_list_item_get_item()返回的是GObject*实例(此处为GtkStringObject),直接将其强制转换为const char*会导致程序把对象的内存地址当作字符串传递,从而触发UTF-8无效警告和乱码。

正确做法是调用gtk_string_object_get_string()获取GtkStringObject内部存储的字符串:

static void bind_list_item_cb (GtkListItemFactory *factory, GtkListItem  *list_item)
{
        GtkWidget *label = gtk_list_item_get_child (list_item);
        GtkStringObject *string_obj = GTK_STRING_OBJECT(gtk_list_item_get_item(list_item));
        const char *string = gtk_string_object_get_string(string_obj);
        gtk_label_set_text (GTK_LABEL (label), string);
}

2. 次要问题:ListView初始化时Factory未定义

创建list_view时传入的factory是未初始化的NULL指针,虽然之后通过gtk_list_view_set_factory()补设了工厂,但为了代码严谨性,建议先创建factory再初始化ListView:

// 先创建工厂并绑定信号
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item_cb), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item_cb), NULL);

// 使用已初始化的工厂创建ListView
list_view = gtk_list_view_new (GTK_SELECTION_MODEL(selection), factory);

修正后的完整代码

#include <gtk/gtk.h>

static GListModel* create_model()
{
        GListStore *store;
        store = g_list_store_new(G_TYPE_OBJECT);
        g_list_store_append(store, gtk_string_object_new("London"));
        g_list_store_append(store, gtk_string_object_new("Paris"));
        g_list_store_append(store, gtk_string_object_new("Berlin"));

        return G_LIST_MODEL (store);
}

static void setup_list_item_cb (GtkListItemFactory *factory, GtkListItem *list_item)
{
        GtkWidget *label = gtk_label_new (NULL);
        gtk_list_item_set_child (GTK_LIST_ITEM(list_item), label);
}

static void bind_list_item_cb (GtkListItemFactory *factory, GtkListItem  *list_item)
{
        GtkWidget *label = gtk_list_item_get_child (list_item);
        GtkStringObject *string_obj = GTK_STRING_OBJECT(gtk_list_item_get_item(list_item));
        const char *string = gtk_string_object_get_string(string_obj);
        gtk_label_set_text (GTK_LABEL (label), string);
}

static void activate (GtkApplication *app, gpointer user_data)
{
        GtkWidget *window; GtkWidget *scrolled_window;
        GtkWidget *list_view;
        GtkListItemFactory *factory;
        GListModel *model;

        model = create_model();
        GtkSingleSelection *selection;
        selection = gtk_single_selection_new(G_LIST_MODEL(model));
        gtk_single_selection_set_autoselect(selection,TRUE);

        window = gtk_application_window_new (app);
        gtk_window_set_title (GTK_WINDOW (window), "ListView Example");
        gtk_window_set_default_size (GTK_WINDOW (window), 300, 200);
        scrolled_window = gtk_scrolled_window_new ();
        gtk_window_set_child (GTK_WINDOW (window), scrolled_window);

        // 先创建工厂并绑定信号
        factory = gtk_signal_list_item_factory_new ();
        g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item_cb), NULL);
        g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item_cb), NULL);

        // 使用已初始化的工厂创建ListView
        list_view = gtk_list_view_new (GTK_SELECTION_MODEL(selection), factory);
        gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window), list_view);

        gtk_window_present (GTK_WINDOW (window));
}

int main (int argc, char **argv)
{
        GtkApplication *app; int status;

        app = gtk_application_new ("org.gtk.listview", G_APPLICATION_DEFAULT_FLAGS);
        g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
        status = g_application_run (G_APPLICATION (app), argc, argv);
        g_object_unref (app);
        return status;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 23:00:10