处理从较低级对象引发的事件
Handling events raised from a lower level object
我正在用GTK+3.0编写一个c++程序。无论如何,我认为这个问题可能适用于任何使用事件/信号的框架。
我有一个容器类,说containerClass
和一个子类,说childClass
。childClass
对象child
包含在containerClass
对象container
中。
child
对象是用来修改某些东西的属性的。为此,它有GtkEntry
、GtkButton
等。当我单击"保存按钮"时,会引发一个事件。
此事件必须由container
对象处理,因为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!!!
}
这个方法很有效。无论如何,我想知道是否有一种更聪明、更干净的方法来实现同样的目标,也许不使用指向静态函数的指针,或者通过定义某种模式来重用每次我需要相同的机制。
Thanks in advance
Gtkmm使用sig++库为您处理所有这些。没有必要自己写。
文档链接:
- 号概述gh>
- 附详细资料的附录
在本例中,我将使用
button.signal_clicked().connect(sigc::mem_fun(container, &containerClass::clickHandler));
同时确保containerClass::clickHander
有适当数量的参数
我的第一个建议是使用use模板来提高你正在做的事情的类型安全性:
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,从而在分派事件时导致后端崩溃。
我的下一步将带我们进一步从你的实现,但将需要更多的细节,你实际上在做什么。根据您的需要,我们将查看:
- 继承:容器类应该从childClass派生吗?这将提供对可以重写的虚函数表的访问。
- 函数:参考boost::function和boost::bind来实现函数,消除了中间的静态函数调用。
- Lambda函数:前沿(c++ 11或更高版本),但可能很适合这种转发函数。
相关文章:
- 在事件过滤器之前发出对象的事件
- 对象销毁后的事件
- 如何在OpenGL中使用关键事件来转换对象
- 在另一个 QThread 上运行成员方法时,无法将事件发送到其他线程拥有的对象
- 是否可以在C++(17)中捕获某些对象属性的破坏性赋值事件
- 如何在主事件循环之前创建一些对象?
- QT:QT无法将事件发送到另一个线程拥有的对象 - 原因
- WXWIDGETS将鼠标事件连接到WXPAINTDC上的形状对象以删除
- 是否有任何可能的方法将事件(自定义)附加到在运行时创建的对象?[C 构建器]
- 将 ETW 文件对象与 DiskIO 事件相关联
- 是否有任何对象可以用作FIFO和弹出数据的事件
- C++使用 shared_ptr 安全地删除事件对象有效负载
- 将C 对象暴露于QML并收听更改事件
- 无法在另一个线程-QT中向对象发送已发布的事件
- Qt 事件过滤器未检测到对象名称
- Win32获取从窗口WNDProc发送事件的对象的HWND
- 如何设置并发::事件对象,仅当它现在未处于信号状态时
- 我可以在 QP(量子平台)活动对象中等待 Windows 事件(WaitForMultipleObjects)吗?
- 如何调试是否设置了 Windows 事件对象
- 不接受c++类的事件对象