解除绑定lambda事件处理程序

问题描述:

如何取消绑定我绑定的事件处理程序,如下所示?解除绑定lambda事件处理程序

MyFrame::MyFrame() 
{ 
    Bind(wxEVT_COMMAND_MENU_SELECTED, 
     [](wxCommandEvent&) { 
      // Do something useful 
     }, 

     wxID_EXIT); 
} 

非常感谢您的第一个答案。我已经添加了一些附加信息。

通过使用具体的Functor解除事件处理程序的可能性被记录并且工作正常,但是如果使用C++ 11 lambda样式绑定某些事件,则以后没有Functor availibale可以调用unbind方法。如果相应的wxEvtHandler应该被破坏,这会造成麻烦。

有没有“窍门”。 。 。如果没有,我没有看到一个真正的用例绑定使用lambda仿函数。 希望我错了。 。 。

非常感谢
Hacki

+0

的可能的复制[wxWidgets的:作为其触发事件解除绑定(http://stackoverflow.com/questions/18955287/wxwidgets-unbind-event-as-its-triggered) – CamFerry

+0

@CamFerry,没有它是不。解绑定函数需要事件处理函数名称,并且这里没有带lambda的名称。它可能是C++ 11中的一些东西...... – Igor

不能解除绑定时调用绑有拉姆达,为你的榜样。如果你存储了lambda,那么你可以解除绑定,例如

class MyFrame 
{ 
    ... 
    std::function<void()> DoUnbind; 
} 

MyFrame::MyFrame() 
{ 
    auto DoSomethingUseful = [](wxCommandEvent&) { 
      // Do something useful 
     }; 

    Bind(wxEVT_COMMAND_MENU_SELECTED, 
     DoSomethingUseful, 
     wxID_EXIT); 

    DoUnbind = [DoSomethingUseful](){ 
     Unbind(wxEVT_COMMAND_MENU_SELECTED, 
       DoSomethingUseful, 
       wxID_EXIT); 
    }; 
} 
+1

为什么会这样?根据评论,你必须使用函子的地址来解除绑定。您按值捕获,所以'DoUnbind'有一个lambda的新副本,它不会与最初绑定的地址具有相同的地址。 –

wxWidget's documentation指定Unbind作品仿函数(lambda表达式和也)的确切方式:

目前仿函数由它们的地址相比,遗憾的是不正确的,如果相同的地址是工作重用于两个不同的函子对象。

所以,如果你想可靠Unbind一些仿函数,你应该保存在由BindUnbind呼叫站点共享一个特殊的地方函子,然后通过完全相同的对象这两个函数(他们需要const-references尽管文件没有反映出来)。

这适用于lambdas和函子,所以它甚至不是C++ 11特有的。如果你想Unbind的东西,这东西应该有一个固定的地址在内存中。因此,它应该有一个名称。这有点杀死了lambda的美丽。

所以,这应该工作:

static auto event_handler = [](wxCommandEvent&) { 
    // Do something 
}; 
// ... 
Bind(..., event_handler, ...); 
// ... 
Unbind(..., event_handler, ...); 

但是,即使这不(或做,这取决于你的运气与临时变量的位置):

struct EventHandler { 
    void operator()(wxCommandEvent&) const { 
    // Do something 
    } 
}; 
// ... 
Bind(..., EventHandler(), ...); 
// ... 
Unbind(..., EventHandler(), ...); 

当程序执行完毕,所有事件处理程序将从所有控件中解除绑定。即使对于lambda来说也是如此。

这是非常罕见的,你需要解除用户代码内的东西,但如果你做@Caleth的答案将工作。

不幸的是,目前没有办法做到这一点,你需要将你的lambda存储在一个对象中以给它一个标识,

auto const handler = [](wxCommandEvent&) { ... }; 

// To bind it: 
Bind(wxEVT_MENU, handler, wxID_EXIT); 

// To unbind it: 
Unbind(wxEVT_MENU, handler, wxID_EXIT);