处理从较低级别引发的事件 object
Handling events raised from a lower level object
我正在使用 GTK+3.0 编写 C++ 程序。无论如何,我认为这个问题可能适用于任何使用事件/信号的框架。
我有一个容器 class,比如 containerClass
和一个 child class,比如 childClass
。 childClass
object child
包含在 containerClass
object container
中。
child
object 是为了修改某物的属性而写的。为此,它有GtkEntry
、GtkButton
等。当我单击 "save button" 时,会引发一个事件。
此事件必须由 container
object 处理,因为 container
以某种方式与数据库连接。
此后,您将找到我用来完成这项工作的解决方案:
// Child class
class childClass {
void setClickHandler_External(void (*extFun)(string property), void *);
void (*clickHandler_External)(string, void *);
void *clickHandler_External_Data;
static void buttonClicked(GtkWidget *widget, void *data);
}
void childClass::setClickHandler_External(void (*extFun)(string), void *data) {
// Set the external event handler
clickHandler_External = extFun;
clickHandler_External_Data = data;
}
void childClass::buttonClicked(GtkWidget *widget, void *data) {
childClass *m = (childClass *)data;
// Call the external event handler
m->clickHandler_External(property, m->clickHandler_External_Data);
}
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, void *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External((void(*)(string))&(this->clickHandler), (void *)this);
}
void containerClass::clickHandler(string property, void *data) {
// Event handler in the upper class
containerClass *m = (containerClass *)data;
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
这很好用并且可以完成工作。无论如何,我想知道是否有更聪明、更简洁的方法来实现相同的目标,也许不使用指向静态函数的指针,或者通过定义某种模式以便每次我需要具有相同的机制时重用。
提前致谢
我的第一个建议是使用模板来提高您正在做的事情的类型安全性:
template< class ParamType >
void childClass::setClickHandler_External(void (*extFun)(string, ParamType *),
ParamType *data)
{
// Set the external event handler
clickHandler_External = (void ()(string,void*))extFun;
clickHandler_External_Data = (void*)data;
}
那么你可以这样简化containerClass的实现:
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, containerClass *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External(&containerClass::clickHandler, this);
}
void containerClass::clickHandler(string property, containerClass *data) {
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
虽然这很好地清理了实现,从所有容器实现者中删除了显式转换,但这并不是真正的重点。重点是防止您将错误的指针传递给 setClickHandler_External,导致调度事件时后端崩溃。
我的下一步将使我们进一步了解您的实施,但需要有关您实际执行的操作的更多详细信息。根据您的需要,将调查:
- 继承:containerClass 是否应该派生自 childClass?这将提供对我们可以覆盖的虚函数 table 的访问。
- 仿函数:查看 boost::function 和 boost::bind 来实现仿函数,消除中间静态函数调用。
- Lambda 函数:前沿(C++11 或更高版本),但可能非常适合这种转发函数。
Gtkmm 使用 sigc++ 库为您处理所有这一切。不用自己写了
文档链接:
所以,在这种情况下,我会使用类似
的东西
button.signal_clicked().connect(sigc::mem_fun(container, &containerClass::clickHandler));
同时确保 containerClass::clickHander
具有适当数量的参数。
我正在使用 GTK+3.0 编写 C++ 程序。无论如何,我认为这个问题可能适用于任何使用事件/信号的框架。
我有一个容器 class,比如 containerClass
和一个 child class,比如 childClass
。 childClass
object child
包含在 containerClass
object container
中。
child
object 是为了修改某物的属性而写的。为此,它有GtkEntry
、GtkButton
等。当我单击 "save button" 时,会引发一个事件。
此事件必须由 container
object 处理,因为 container
以某种方式与数据库连接。
此后,您将找到我用来完成这项工作的解决方案:
// Child class
class childClass {
void setClickHandler_External(void (*extFun)(string property), void *);
void (*clickHandler_External)(string, void *);
void *clickHandler_External_Data;
static void buttonClicked(GtkWidget *widget, void *data);
}
void childClass::setClickHandler_External(void (*extFun)(string), void *data) {
// Set the external event handler
clickHandler_External = extFun;
clickHandler_External_Data = data;
}
void childClass::buttonClicked(GtkWidget *widget, void *data) {
childClass *m = (childClass *)data;
// Call the external event handler
m->clickHandler_External(property, m->clickHandler_External_Data);
}
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, void *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External((void(*)(string))&(this->clickHandler), (void *)this);
}
void containerClass::clickHandler(string property, void *data) {
// Event handler in the upper class
containerClass *m = (containerClass *)data;
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
这很好用并且可以完成工作。无论如何,我想知道是否有更聪明、更简洁的方法来实现相同的目标,也许不使用指向静态函数的指针,或者通过定义某种模式以便每次我需要具有相同的机制时重用。
提前致谢
我的第一个建议是使用模板来提高您正在做的事情的类型安全性:
template< class ParamType >
void childClass::setClickHandler_External(void (*extFun)(string, ParamType *),
ParamType *data)
{
// Set the external event handler
clickHandler_External = (void ()(string,void*))extFun;
clickHandler_External_Data = (void*)data;
}
那么你可以这样简化containerClass的实现:
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, containerClass *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External(&containerClass::clickHandler, this);
}
void containerClass::clickHandler(string property, containerClass *data) {
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
虽然这很好地清理了实现,从所有容器实现者中删除了显式转换,但这并不是真正的重点。重点是防止您将错误的指针传递给 setClickHandler_External,导致调度事件时后端崩溃。
我的下一步将使我们进一步了解您的实施,但需要有关您实际执行的操作的更多详细信息。根据您的需要,将调查:
- 继承:containerClass 是否应该派生自 childClass?这将提供对我们可以覆盖的虚函数 table 的访问。
- 仿函数:查看 boost::function 和 boost::bind 来实现仿函数,消除中间静态函数调用。
- Lambda 函数:前沿(C++11 或更高版本),但可能非常适合这种转发函数。
Gtkmm 使用 sigc++ 库为您处理所有这一切。不用自己写了
文档链接:
所以,在这种情况下,我会使用类似
的东西button.signal_clicked().connect(sigc::mem_fun(container, &containerClass::clickHandler));
同时确保 containerClass::clickHander
具有适当数量的参数。