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

在gtkmm 3.24.5中如何为Widget添加销毁sigc回调?

当然可以实现!

虽然Gtk::Widget在gtkmm 3.24.5里没有直接暴露销毁相关的信号,但它的底层C API(GtkWidget)继承自GObject,而GObject本身提供了destroy信号——这个信号会在对象引用计数降为0、即将被销毁时触发,完全符合你的需求。

你可以通过两种方式把这个C API信号连接到sigc回调:

方法1:用Glib提供的便捷包装(推荐)

Glib为gtkmm提供了Glib::signal_connect函数,可以直接把GObject的信号绑定到sigc风格的回调,不需要手动写C风格的包装函数:

#include <gtkmm.h>

// 示例回调函数
void on_widget_destroyed() {
    std::cout << "Widget 已销毁!" << std::endl;
}

int main(int argc, char* argv[]) {
    auto app = Gtk::Application::create(argc, argv, "com.example.demo");

    Gtk::Window window;
    Gtk::Button btn("关闭窗口");
    window.add(btn);

    // 连接GObject的destroy信号到sigc回调
    Glib::signal_connect(btn.gobj(), "destroy", sigc::ptr_fun(&on_widget_destroyed));

    btn.signal_clicked().connect([&window]() { window.close(); });

    window.show_all();
    return app->run(window);
}

如果要绑定类的成员函数,也很简单:

class MyAppWindow : public Gtk::Window {
public:
    MyAppWindow() {
        auto btn = Gtk::manage(new Gtk::Button("关闭"));
        add(*btn);

        // 绑定成员函数作为销毁回调
        Glib::signal_connect(btn->gobj(), "destroy", 
            sigc::mem_fun(*this, &MyAppWindow::on_button_destroyed));

        btn->signal_clicked().connect(sigc::mem_fun(*this, &MyAppWindow::on_close_clicked));
        show_all();
    }

private:
    void on_button_destroyed() {
        std::cout << "按钮已被销毁" << std::endl;
    }

    void on_close_clicked() {
        close();
    }
};

方法2:直接使用C API的g_signal_connect

如果你想更直接地操作底层C API,可以用g_signal_connect,需要自己把sigc回调包装成C风格的函数:

#include <gtkmm.h>
#include <glib.h>

void on_widget_destroyed() {
    std::cout << "Widget 销毁触发" << std::endl;
}

// C风格的包装函数
static void c_destroy_callback(gpointer data) {
    // 把传入的data转换为sigc槽并调用
    auto callback = *static_cast<sigc::slot<void>*>(data);
    callback();
    // 记得释放槽的内存(如果是动态分配的)
    delete static_cast<sigc::slot<void>*>(data);
}

int main(int argc, char* argv[]) {
    auto app = Gtk::Application::create(argc, argv, "com.example.demo");

    Gtk::Window window;
    Gtk::Button btn("关闭");
    window.add(btn);

    // 获取底层GObject指针
    GObject* gobj = G_OBJECT(btn.gobj());
    // 动态分配sigc槽,作为参数传给C回调
    auto slot = new sigc::slot<void>(sigc::ptr_fun(&on_widget_destroyed));
    g_signal_connect(gobj, "destroy", G_CALLBACK(c_destroy_callback), slot);

    btn.signal_clicked().connect([&window]() { window.close(); });

    window.show_all();
    return app->run(window);
}

注意事项

  • destroy信号触发时,widget已经处于销毁流程中,此时不要尝试访问widget的成员或调用其方法,避免出现未定义行为。
  • 如果你使用方法2,要注意管理好sigc槽的内存,避免内存泄漏。
  • 这个方法适用于所有继承自GObject的gtkmm控件,不止是Gtk::Widget。

内容的提问来源于stack exchange,提问作者SVA522

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:20:19