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
相关产品推荐
相关产品推荐

