You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 15:17:05