请求提供Gtkmm函数g_timeout_add的正确使用示例
解决Gtkmm中g_timeout_add调用类成员函数的问题
这个问题我之前也碰到过,核心原因是g_timeout_add作为GLib的C原生API,没法直接用C++类的非静态成员函数当回调——因为这类成员函数会自动携带一个隐含的this指针,和它要求的GSourceFunc函数签名完全不匹配,这就是你不管加不加&都会报错的根源。
下面给你两种可行的解决方案,优先推荐第二种更贴合C++风格的写法:
方案一:用静态成员函数做包装器(兼容C API)
我们可以先写一个静态成员函数,它符合g_timeout_add要求的回调签名,然后把类实例的this指针作为数据传递进去,在静态函数里再转成实例指针调用真正的成员函数。如果需要传递额外的processed参数,还可以把this和processed打包成结构体:
#include <gtkmm/window.h> #include <iostream> #include <utility> class MainWindow : public Gtk::Window { public: MainWindow(int processed) { // 把当前实例指针和processed打包成结构体传递 auto* data = new std::pair<MainWindow*, int>(this, processed); g_timeout_add(100, &MainWindow::static_callback, data); } // 记得在析构里清理内存(避免泄漏) ~MainWindow() override { // 如果定时还在运行,建议先通过g_source_remove移除对应的源,这里简化处理 } private: // 静态成员函数,完全符合GSourceFunc的签名 static gboolean static_callback(gpointer data) { // 解析传递过来的数据 auto* pair = static_cast<std::pair<MainWindow*, int>*>(data); MainWindow* window = pair->first; int processed_val = pair->second; // 调用实际的成员回调函数 bool keep_running = window->callbackFunc(processed_val); // 如果不需要继续定时,清理内存 if (!keep_running) { delete pair; } // 转换为gboolean返回(TRUE继续,FALSE停止) return keep_running ? TRUE : FALSE; } // 你实际的业务回调函数 bool callbackFunc(int processed_val) { // 这里写你的处理逻辑 std::cout << "Timeout triggered, processed value: " << processed_val << std::endl; // 返回true继续定时,返回false停止 return true; } };
方案二:用Gtkmm的C++风格超时信号(推荐)
Gtkmm作为GLib的C++绑定,提供了更友好的Glib::signal_timeout()接口,不需要手动处理静态包装和指针转换,直接用sigc::mem_fun绑定成员函数,还能通过sigc::bind传递额外参数:
#include <gtkmm/window.h> #include <glibmm/main.h> #include <iostream> class MainWindow : public Gtk::Window { public: MainWindow(int processed) { // 绑定超时信号,100毫秒触发一次,同时传递processed参数 Glib::signal_timeout().connect( sigc::bind(sigc::mem_fun(*this, &MainWindow::callbackFunc), processed), 100 ); } private: // 回调函数直接用bool返回(和gboolean兼容) bool callbackFunc(int processed_val) { std::cout << "Timeout triggered, processed value: " << processed_val << std::endl; // 返回true继续定时,false停止 return true; } };
关键说明:
- 如果不需要传递额外参数,直接用
sigc::mem_fun(*this, &MainWindow::callbackFunc)即可,不需要sigc::bind。 - 两种方案中,回调函数返回
true(或TRUE)表示继续触发定时,返回false(或FALSE)表示停止定时。
内容的提问来源于stack exchange,提问作者Razvan
相关产品推荐
相关产品推荐

