GTK4+Glade模态表单输入验证:输入值获取为空问题求助
GTK4模态表单获取输入值为空的问题解决
1. 变量为空的原因
你在on_button_confirm_clicked回调中重新调用了gtk_builder_new_from_file("design.glade"),这会创建一个全新的UI控件树,和用户正在输入的那个模态窗口完全是两个独立的对象。你获取的输入框是这个新树里的空实例,自然读不到用户之前输入的内容。
2. 正确获取并验证输入值的方法
有两种可靠的方式解决这个问题:
方法一:从模态窗口直接查找子控件
利用GTK4的gtk_widget_find_child()函数,直接从已显示的模态窗口中查找输入框控件,无需重新加载Glade文件:
void on_button_confirm_clicked(GtkButton *button, gpointer user_data) { GtkWidget *modal_window = GTK_WIDGET(user_data); // 从模态窗口中查找指定名字的输入控件 GtkWidget *first_name_entry = gtk_widget_find_child(modal_window, "first_name_entry"); GtkWidget *second_name_entry = gtk_widget_find_child(modal_window, "second_name_entry"); GtkWidget *id_entry = gtk_widget_find_child(modal_window, "id_entry"); // 检查控件是否找到 if (!first_name_entry || !second_name_entry || !id_entry) { g_warning("无法找到输入控件"); return; } const char *first_name = gtk_editable_get_text(GTK_EDITABLE(first_name_entry)); const char *second_name = gtk_editable_get_text(GTK_EDITABLE(second_name_entry)); const char *id_text = gtk_editable_get_text(GTK_EDITABLE(id_entry)); // 验证逻辑 if (strlen(first_name) == 0) { printf("输入为空 "); } else { printf("名字:%s\n", first_name); } // 关闭模态窗口 gtk_window_close(GTK_WINDOW(modal_window)); }
方法二:传递真实控件的引用给回调
在创建模态窗口时,将输入框的引用打包成结构体,作为user_data传递给确认按钮的回调,确保操作的是用户交互的真实控件:
首先定义存储控件引用的结构体:
typedef struct { GtkWidget *first_name_entry; GtkWidget *second_name_entry; GtkWidget *id_entry; GtkWidget *modal_window; } ModalData;
修改添加按钮的回调:
void on_button_add_clicked(GtkButton *button, gpointer user_data) { printf("添加按钮被点击\n"); GtkBuilder *builder = gtk_builder_new_from_file("design.glade"); GtkWidget *modal_window = GTK_WIDGET(gtk_builder_get_object(builder, "add_item_modal")); GtkWidget *confirm_button = GTK_WIDGET(gtk_builder_get_object(builder, "button_confirm")); // 分配结构体并存储控件引用 ModalData *data = g_new(ModalData, 1); data->first_name_entry = GTK_WIDGET(gtk_builder_get_object(builder, "first_name_entry")); data->second_name_entry = GTK_WIDGET(gtk_builder_get_object(builder, "second_name_entry")); data->id_entry = GTK_WIDGET(gtk_builder_get_object(builder, "id_entry")); data->modal_window = modal_window; // 增加控件引用计数,防止提前销毁 g_object_ref(data->first_name_entry); g_object_ref(data->second_name_entry); g_object_ref(data->id_entry); g_object_ref(data->modal_window); // 设置模态窗口的父窗口 GtkWindow *parent_window = GTK_WINDOW(user_data); gtk_window_set_transient_for(GTK_WINDOW(modal_window), parent_window); // 连接确认按钮信号,传递结构体 g_signal_connect(confirm_button, "clicked", G_CALLBACK(on_button_confirm_clicked), data); // 连接窗口关闭信号,释放资源 g_signal_connect(modal_window, "close-request", G_CALLBACK(on_modal_closed), data); gtk_window_present(GTK_WINDOW(modal_window)); g_object_unref(builder); }
添加窗口关闭的回调用于释放资源:
void on_modal_closed(GtkWindow *window, gpointer user_data) { ModalData *data = (ModalData*)user_data; // 释放控件引用 g_object_unref(data->first_name_entry); g_object_unref(data->second_name_entry); g_object_unref(data->id_entry); g_object_unref(data->modal_window); // 释放结构体内存 g_free(data); }
最后修改确认按钮的回调:
void on_button_confirm_clicked(GtkButton *button, gpointer user_data) { ModalData *data = (ModalData*)user_data; const char *first_name = gtk_editable_get_text(GTK_EDITABLE(data->first_name_entry)); const char *second_name = gtk_editable_get_text(GTK_EDITABLE(data->second_name_entry)); const char *id_text = gtk_editable_get_text(GTK_EDITABLE(data->id_entry)); // 验证逻辑 if (strlen(first_name) == 0) { printf("输入为空 "); } else { printf("名字:%s\n", first_name); } // 关闭模态窗口 gtk_window_close(GTK_WINDOW(data->modal_window)); }
注意事项
- 不要在回调中重复加载Glade文件,这会创建新的控件实例,无法获取用户输入。
- 处理GTK对象的引用计数,避免内存泄漏或控件提前销毁。
内容的提问来源于stack exchange,提问作者Oussama
相关产品推荐
相关产品推荐

