GTK3结合Glade读取SQLite3数据动态切换图片仅显示最后一张如何解决
问题根因
GTK采用单线程事件驱动的主循环机制,你的回调函数add_image_cb是在主循环线程中执行的,在函数执行完成前,GTK不会处理任何UI重绘请求,所以你在while循环里快速切换图片的操作都被积压了,等函数执行完只留下最后一次添加的图片生效。哪怕你取消注释sleep(1)也没用,sleep只会阻塞整个主循环,UI完全卡住不会更新。
同时你的原代码还存在SQLite资源泄漏问题:sqlite3_prepare_v2创建的语句对象没有调用sqlite3_finalize释放,也没有关闭数据库连接。
修复方案
你需要把轮播逻辑拆成两步:首先一次性从SQLite读取所有文件名存到列表里,再用GTK的定时器g_timeout_add定时切换图片,不阻塞主循环。
步骤1:先定义全局/静态变量存储轮播所需数据
// 可根据需求调整存储方式,全局变量方便跨回调调用 static GList *image_path_list = NULL; // 存储所有图片路径 static guint timer_id = 0; // 定时器ID static gint current_index = 0; // 当前展示的图片索引 static GtkWidget *current_image = NULL; // 当前展示的图片控件
步骤2:修改按钮回调函数,仅做数据读取和定时器注册
G_MODULE_EXPORT void add_image_cb(GtkButton *button) { sqlite3 * db; char * sql; sqlite3_stmt * stmt; int s; char jpeg[] = ".jpg"; char name[30]; // 先清理之前的轮播残留资源 if (timer_id > 0) { g_source_remove(timer_id); timer_id = 0; } if (image_path_list) { g_list_free_full(image_path_list, g_free); image_path_list = NULL; } current_index = 0; // 读取所有文件名存入列表 sqlite3_open("list.db", &db); sql = "SELECT name FROM name_list"; sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL); while((s = sqlite3_step(stmt)) == SQLITE_ROW) { const unsigned char * text = sqlite3_column_text(stmt, 0); strcpy(name, text); strcat(name, jpeg); image_path_list = g_list_append(image_path_list, g_strdup(name)); } // 释放SQLite资源 sqlite3_finalize(stmt); sqlite3_close(db); if (g_list_length(image_path_list) == 0) return; // 注册定时器,每1000ms(1秒)切换一次图片,单位可自行调整 timer_id = g_timeout_add(1000, (GSourceFunc)switch_image, NULL); }
步骤3:实现定时器回调函数,单独处理图片切换逻辑
gboolean switch_image(gpointer user_data) { gint total = g_list_length(image_path_list); if (total == 0) return G_SOURCE_REMOVE; // 移除之前的图片控件 if (current_image) { gtk_container_remove(GTK_CONTAINER(fixed1), current_image); current_image = NULL; } // 加载当前索引对应的图片 gchar *path = g_list_nth_data(image_path_list, current_index); current_image = gtk_image_new_from_file(path); gtk_widget_show(current_image); gtk_container_add(GTK_CONTAINER(fixed1), current_image); // 索引自增,到末尾自动循环 current_index = (current_index + 1) % total; return G_SOURCE_CONTINUE; // 保持定时器持续执行 }
编译命令保持不变
gcc `pkg-config --cflags gtk+-3.0` -rdynamic -o test2 test2.c `pkg-config --libs gtk+-3.0` -lsqlite3 -std=c99
内容的提问来源于stack exchange,提问作者NACHANON AIMSRICHAROEN
相关产品推荐
相关产品推荐

