Lambda表达式处理事件回调函数
C++11开始支持Lambda表达式,Lambda表达式除了可以作为匿名函数使用,还可以通过捕获列表访问环境中的变量。在UI编程中使用Lambda表达式替代传统的函数指针处理回调函数,不仅可以简化代码提高可读性,还可以减少参数传递提高灵活性。下面针对常用的C++ UI库尝试实现相关操作。
1. wxWidgets事件绑定
1.1 wxWidgets事件机制
wxWidgets有两套事件机制,一套是静态的事件表1,另一套是动态事件机制2。动态事件提供了两套API,分别是Connect()和Bind()3,后者较新,前者已经淘汰。
实际上Bind()是原生支持Lambda表达式的,我们可以将官方文档的示例代码4改写如下。
// --- main.cpp ---
#include <wx/wx.h>
enum
{
ID_Hello = 1
};
class MyFrame : public wxFrame
{
public:
MyFrame()
: wxFrame(nullptr, wxID_ANY, "Hello World")
{
wxMenu *menuFile = new wxMenu;
menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
wxMenu *menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuFile, "&File");
menuBar->Append(menuHelp, "&Help");
SetMenuBar(menuBar);
CreateStatusBar();
SetStatusText("Welcome to wxWidgets!");
Bind(wxEVT_MENU, [](wxCommandEvent &event)
{ wxLogMessage("Hello world from wxWidgets!"); }, ID_Hello);
Bind(wxEVT_MENU, [](wxCommandEvent &event)
{ wxMessageBox("This is a wxWidgets Hello World example",
"About Hello World", wxOK | wxICON_INFORMATION); }, wxID_ABOUT);
Bind(wxEVT_MENU, [this](wxCommandEvent &event)
{ this->Close(true); }, wxID_EXIT);
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
MyFrame *frame = new MyFrame();
frame->Show(true);
return true;
}
};
wxIMPLEMENT_APP(MyApp);
注意Bind()函数传入的参数个数,这里不再需要传入this指针。使用Lambda表达式改写之后窗口类的成员函数基本不需要定义,需要调用对象自身的方法执行特定操作时(比如执行关闭窗口操作),可以通过捕获列表获取对象的this指针。