在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
相关产品推荐
相关产品推荐

