Use Bind() instead of event tables on the "Hello World" page

Let the new users know that Bind() is the preferred way to handle events in
modern wxWidgets.
This commit is contained in:
Vadim Zeitlin 2016-08-27 18:49:30 +02:00
parent 7f26deb13e
commit 2d56fb5298

View File

@ -51,11 +51,14 @@ menu and a status bar in its constructor. Also, any class that wishes to
respond to any "event" (such as mouse clicks or messages from the menu or a
button) must declare an event table using the macro below.
Finally, the way to react to such events must be done in "handlers". In our
sample, we react to three menu items, one for our custom menu command and two
for the standard "Exit" and "About" commands (any program should normally
implement the latter two). Notice that these handlers don't need to be neither
virtual nor public.
Finally, the way to react to such events must be done in "event handlers" which
are just functions (or functors, including lambdas if you're using C++11)
taking the @c event parameter of the type corresponding to the event being
handled, e.g. wxCommandEvent for the events from simple controls such as
buttons, text fields and also menu items. In our sample, we react to three menu
items, one for our custom menu command and two for the standard "Exit" and
"About" commands (any program should normally implement the latter two). Notice
that these handlers don't need to be neither virtual nor public.
@code
class MyFrame: public wxFrame
@ -67,8 +70,6 @@ private:
void OnHello(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
};
@endcode
@ -83,28 +84,10 @@ enum
};
@endcode
Notice that you don't need to define identifiers for the "About" and "Exit". We
then proceed to actually implement an event table in which the events are
routed to their respective handler functions in the class MyFrame.
There are predefined macros for routing all common events, ranging from the
selection of a list box entry to a resize event when a user resizes a window on
the screen. If @c wxID_ANY is given as the ID, the given handler will be
invoked for any event of the specified type, so that you could add just one
entry in the event table for all menu commands or all button commands etc.
The origin of the event can still be distinguished in the event handler as the
(only) parameter in an event handler is a reference to a wxEvent object, which
holds various information about the event (such as the ID of and a pointer to
the class, which emitted the event).
@code
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Hello, MyFrame::OnHello)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()
@endcode
Notice that you don't need to define identifiers for the "About" and "Exit" as
wxWidgets already predefines and the standard values such as wxID_ABOUT and
wxID_EXIT should be used whenever possible, as they can be handled in a special
way by a particular platform.
As in all programs there must be a "main" function. Under wxWidgets main is
implemented inside ::wxIMPLEMENT_APP() macro, which creates an application
@ -156,7 +139,8 @@ MyFrame::MyFrame()
CreateStatusBar();
SetStatusText( "Welcome to wxWidgets!" );
}
... continued below ...
@endcode
Notice that we don't need to specify the labels for the standard menu items
@ -165,6 +149,32 @@ translated) labels and also standard accelerators correct for the current
platform making your program behaviour more native. For this reason you should
prefer reusing the standard ids (see @ref page_stockitems) if possible.
We also have to actually connect our event handlers to the events we want to
handle in them, by calling Bind() to send all the menu events, identified by
wxEVT_MENU event type, with the specified ID to the given function. The
parameters we pass to Bind() are
-# The event type, e.g. wxEVT_MENU or wxEVT_BUTTON or wxEVT_SIZE or one
of many other events used by wxWidgets.
-# Pointer to the member function to call and the object to call it on. In
this case we just call our own function, hence we pass `this` for this
object itself, but we could call a member function of another object too.
And we could could also use a non-member function here, and, in fact,
anything that can be called passing it a wxCommandEvent could be used here.
-# The optional identifier allowing to select just some events of wxEVT_MENU
type, namely those from the menu item with the given ID, instead of handling
all of them in the provided handler. This is especially useful with the menu
items and rarely used with other kinds of events.
@code
... continued from above ...
Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello);
Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT);
Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT);
}
@endcode
Here are the standard event handlers implementations. MyFrame::OnExit() closes
the main window by calling Close(). The parameter @true indicates that other
windows have no veto power such as after asking "Do you really want to close?".
@ -226,8 +236,6 @@ private:
void OnHello(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
};
enum
@ -235,12 +243,6 @@ enum
ID_Hello = 1
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Hello, MyFrame::OnHello)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
@ -270,6 +272,10 @@ MyFrame::MyFrame()
CreateStatusBar();
SetStatusText( "Welcome to wxWidgets!" );
Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello);
Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT);
Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT);
}
void MyFrame::OnExit(wxCommandEvent& event)