[英]use gtk_signal_connect with a member function in c++
将GTK +信号连接到非静态成员函数的最佳方法是什么?
我有一个使用gtk的c ++ GUI类,我想做这样的事情:
Gui::Gui ()
{
gtk_signal_connect(GTK_OBJECT(somObject),
"clicked",
GTK_SIGNAL_FUNC( &(this->ClickHandler) ),
NULL);
}
void Gui::ClickHandler(GtkWidget *w, gpointer data)
{
// handle the click
}
我知道这不起作用b / c GTK _SIGNAL
_FUNC不能指向成员函数,除非它是静态函数,那么最好的方法是什么? 有可能使用单个代理处理函数和boost :: bind吗? 这是我尝试过的:
gtk_signal_connect(GTK_OBJECT(somObject), "clicked",
GTK_SIGNAL_FUNC( SigHandler ),
boost::bind( &(Gui::ClickHandler), this) );
void SigHandler(GtkWidget *w, gpointer data)
{
data(w);
}
void Gui::ClickHandler(GtkWidget *w) { // handle the click }
这是错误:gui.cc:错误:'data'不能用作函数
我假设您的类包含信号处理程序需要访问的一些内部数据。 如果没有,只需使用静态函数作为信号处理程序。 否则,这里有几个想法:
从成员函数中创建一个sigc ++或boost functor; 将其设置为传递给信号处理程序的数据。 使用只调用仿函数的通用信号处理程序。
在构造期间,在某处注册类的每个实例,并使用信号处理程序为每个已注册的实例调用成员函数。
您将需要代理,但您可以执行一些模板魔术来帮助您生成代理。 像这样的东西:
template <class HandlerClass, class A1, void(HandlerClass::*HandlerFunc)(A1)>
struct GtkHandlerProxy {
static void HandlerProxy(A1 a1, gpointer p) {
(static_cast<HandlerClass*>(p)->*HandlerFunc)(a1);
}
};
然后使用它:
Gui::Gui()
{
gtk_signal_connect(
GTK_OBJECT(somObject),
"clicked",
GTK_SIGNAL_FUNC(&GtkHandlerProxy<Gui, GtkWidget*, &Gui::ClickHandler>
::HandlerProxy),
this);
}
你可能也想定义一个辅助宏:
#define GTK_SIGNAL_METHOD(Class, Handler, A1) \
GTK_SIGNAL_FUNC(GtkHandlerProxy<Class, A1, &Class::Handler>::HandlerProxy)
这样你就可以写:
Gui::Gui()
{
gtk_signal_connect(
GTK_OBJECT(somObject),
"clicked",
GTK_SIGNAL_METHOD(GtkHandlerProxy, ClickHandler, GtkWidget*),
this);
}
这仅涵盖单参数处理程序案例; 要处理像button_press_event
这样的button_press_event
,你必须为2个以上的参数定义类似的帮助器。 Boost预处理器库可以帮助避免重复代码。
[编辑]
或者,您可以将函数对象本身作为p
传递,它可能包含捕获的变量(例如boost::bind
或boost::lambda
)。 这是看起来如何:
class Gui {
...
// Member to ensure proper lifetime
boost::function<void(GtkWidget*)> clickHandlerFunc;
Gui() {
...
clickHandlerFunc = boost::bind(&Gui::ClickHandler, this);
gtk_signal_connect(
GTK_OBJECT(somObject),
"clicked",
GTK_SIGNAL_FUNC(UniversalHandlerProxy<GtkWidget*>)
&clickHandlerFunc);
}
template <class A1>
static void Gui::UniversalHandlerProxy(A1 a1, gpointer p) {
(*static_cast< boost::function<void(A1)>* >(p))(a1);
}
void Gui::ClickHandler(GtkWidget* w, gpointer p) {
...
}
};
使用静态代理:
Gui::Gui ()
{
gtk_signal_connect(GTK_OBJECT(somObject),
"clicked",
GTK_SIGNAL_FUNC(ClickHandlerProxy),
this);
}
void Gui::ClickHandler(GtkWidget *w)
{ /* handle the click */ }
void Gui::ClickHandlerProxy(GtkWidget *w, gpointer p)
{ static_cast<Gui*>(p)->ClickHandler(w); }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.