GTK4+C语言:点击按钮无法向Box添加Label问题求助
GTK4按钮点击无响应问题修复
你的代码核心问题是传递给回调函数的widgets是栈上的局部变量:在on_activate函数执行完毕后,栈上的struct MyWidgets widgets会被系统回收释放,当按钮点击触发回调时,访问的是已经失效的内存地址,导致程序无法正常执行逻辑(甚至可能直接崩溃)。
修复步骤
将struct MyWidgets改为动态分配内存,确保在回调触发时内存仍然有效:
- 在
on_activate中,用g_new动态创建结构体实例(替代栈上的局部变量) - 为窗口添加
destroy信号回调,在窗口关闭时释放动态分配的内存,避免内存泄漏
修改后的完整代码
#include <gtk/gtk.h> #undef main struct MyWidgets{ GtkWidget* prompt; GtkWidget* box; }; // 释放结构体内存的回调 void on_window_destroy(gpointer data) { struct MyWidgets *widgets = (struct MyWidgets*)data; g_free(widgets); } void on_button_clicked(GtkButton *button, gpointer data) { struct MyWidgets *widgets = (struct MyWidgets*) data; GtkEntryBuffer *buffer = gtk_entry_get_buffer((GtkEntry*)widgets->prompt); const char *text = gtk_entry_buffer_get_text(buffer); GtkWidget *output = gtk_label_new(text); gtk_widget_set_margin_start(output, 30); gtk_box_append((GtkBox*)widgets->box, output); // GTK4中新建的widget默认可见,无需手动调用gtk_widget_set_visible } static void on_activate (GtkApplication *app) { GtkWidget *window = gtk_application_window_new (app); gtk_window_set_resizable((GtkWindow*)window, FALSE); gtk_window_set_default_size((GtkWindow*)(window), 800, 900); GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_box_set_homogeneous((GtkBox*)box, FALSE); GtkWidget *label = gtk_label_new("Enter ebnf expression :"); gtk_label_set_xalign((GtkLabel*)label, 0); gtk_widget_set_margin_start(label, 30); GtkWidget *prompt = gtk_entry_new(); gtk_widget_set_size_request(prompt, 300, 40); gtk_widget_set_margin_start(prompt, 30); gtk_widget_set_margin_end(prompt, 30); GtkWidget *button = gtk_button_new_with_label ("Submit"); gtk_button_set_has_frame((GtkButton*)button, TRUE); gtk_widget_set_margin_start(button, 300); gtk_widget_set_margin_end(button, 300); // 动态分配结构体,替代栈上局部变量 struct MyWidgets *widgets = g_new(struct MyWidgets, 1); widgets->box = box; widgets->prompt = prompt; gtk_box_append((GtkBox*)box, label); gtk_box_append((GtkBox*)box, prompt); gtk_box_append((GtkBox*)box, button); g_signal_connect(button, "clicked", G_CALLBACK(on_button_clicked), widgets); // 绑定窗口销毁信号,释放结构体内存 g_signal_connect(window, "destroy", G_CALLBACK(on_window_destroy), widgets); gtk_window_set_child(GTK_WINDOW(window), box); gtk_window_present (GTK_WINDOW (window)); } int main(int argc, char **argv) { GtkApplication *app = gtk_application_new("org.example.GTKTest", G_APPLICATION_DEFAULT_FLAGS); g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL); int status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); return status; }
额外说明
- GTK4中,通过
gtk_label_new等函数创建的widget默认是可见状态,不需要手动调用gtk_widget_set_visible(output, TRUE) - 动态分配的内存一定要记得在合适的时机释放(比如窗口销毁时),避免内存泄漏
内容的提问来源于stack exchange,提问作者oumaima
相关产品推荐
相关产品推荐

