GTK4模态窗口Confirm按钮信号回调未触发问题求解
GTK4模态窗口Confirm按钮回调未触发的解决方案
问题根源
你每次点击主窗口的「Add」按钮时,都会重新加载Glade文件并创建一个全新的add_item_modal窗口实例,而你在activate函数中为button_confirm绑定信号回调的是另一个完全独立的实例。这就导致你点击的模态窗口里的Confirm按钮,根本没有绑定任何回调函数,自然不会触发预期的逻辑。
修复步骤
1. 复用模态窗口实例,避免重复加载Glade
在activate函数中一次性加载Glade并获取模态窗口引用,将其传递给「Add」按钮的回调,而不是每次点击都重新创建窗口。
2. 调整信号绑定与回调逻辑
- 修改「Add」按钮的信号绑定,传递模态窗口引用而非主窗口
- 简化「Add」按钮的回调函数,直接复用已有的模态窗口实例
- 确保模态窗口的引用计数正确,防止被提前销毁
修改后的关键代码
调整activate函数
static void activate(GtkApplication *app, gpointer user_data) { GtkBuilder *builder; GtkWidget *window; GtkWidget *modal_window; GtkWidget *button_add, *button_delete, *button_show_content, *button_modify_content, *confirm_button; // 初始化TOV文件(保留原有逻辑) FichierTOV *fichier = g_malloc(sizeof(FichierTOV)); initialiserFichierTOV(fichier, MAX_ENREGISTREMENTS); // 一次性加载Glade文件 builder = gtk_builder_new_from_file("design.glade"); // 获取主窗口与按钮 window = GTK_WIDGET(gtk_builder_get_object(builder, "main_window")); button_add = GTK_WIDGET(gtk_builder_get_object(builder, "button_add")); button_delete = GTK_WIDGET(gtk_builder_get_object(builder, "button_delete")); button_show_content = GTK_WIDGET(gtk_builder_get_object(builder, "button_show_content")); button_modify_content = GTK_WIDGET(gtk_builder_get_object(builder, "button_modify_content")); confirm_button = GTK_WIDGET(gtk_builder_get_object(builder, "button_confirm")); if (!window || !button_add || !button_delete || !button_show_content || !button_modify_content || !confirm_button) { g_printerr("Failed to fetch widgets from the Glade file\n"); g_object_unref(builder); return; } gtk_window_set_application(GTK_WINDOW(window), app); // 绑定主窗口按钮信号 g_signal_connect(button_delete, "clicked", G_CALLBACK(on_button_delete_clicked), fichier); g_signal_connect(button_show_content, "clicked", G_CALLBACK(on_button_show_content_clicked), fichier); g_signal_connect(button_modify_content, "clicked", G_CALLBACK(on_button_modify_content_clicked), fichier); // 获取模态窗口并增加引用,避免builder销毁时被释放 modal_window = GTK_WIDGET(gtk_builder_get_object(builder, "add_item_modal")); if (!modal_window) { g_printerr("Failed to fetch modal window from the Glade file\n"); g_object_unref(builder); return; } g_object_ref(modal_window); // 绑定Confirm按钮信号 g_signal_connect(confirm_button, "clicked", G_CALLBACK(on_button_confirm_clicked), modal_window); // 将模态窗口和主窗口打包成结构体传递给Add按钮 typedef struct { GtkWidget *modal; GtkWidget *main; } WindowData; WindowData *data = g_malloc(sizeof(WindowData)); data->modal = modal_window; data->main = window; g_signal_connect_data(button_add, "clicked", G_CALLBACK(on_button_add_clicked), data, (GClosureNotify)g_free, 0); // 显示主窗口 gtk_window_present(GTK_WINDOW(window)); // 释放builder g_object_unref(builder); }
修改on_button_add_clicked回调
void on_button_add_clicked(GtkButton *button, gpointer user_data) { printf("Add button was clicked\n"); WindowData *data = (WindowData*)user_data; GtkWidget *modal_window = data->modal; GtkWindow *parent_window = GTK_WINDOW(data->main); // 设置模态窗口的父窗口 gtk_window_set_transient_for(GTK_WINDOW(modal_window), parent_window); // 显示模态窗口 gtk_window_present(GTK_WINDOW(modal_window)); }
保留原有Confirm按钮回调
void on_button_confirm_clicked(GtkButton *button, gpointer user_data) { GtkWidget *modal_window = GTK_WIDGET(user_data); printf("Confirm button was clicked\n"); // 可添加关闭窗口逻辑:gtk_window_destroy(GTK_WINDOW(modal_window)); }
额外说明
- 不需要修改Glade文件,现有UI结构完全可用
- 使用结构体传递多个参数是GTK中常见的规范做法,比全局变量更安全
- 调用
g_object_ref(modal_window)是为了确保在builder被释放后,模态窗口实例不会被销毁
内容的提问来源于stack exchange,提问作者Oussama
相关产品推荐
相关产品推荐

