动态事件处理方法
This commit is contained in:
parent
fc53babbb8
commit
d07cc4295e
@ -1,5 +1,7 @@
|
||||
#include "event_demo.h"
|
||||
|
||||
#ifndef USE_DYNAMIC_CONNECT
|
||||
// 静态链接
|
||||
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
||||
EVT_MENU(wxID_ABOUT, MainFrame::OnAbout)
|
||||
EVT_MENU(wxID_EXIT, MainFrame::OnQuit)
|
||||
@ -18,11 +20,28 @@ EVT_SIZE(MainFrame::OnSize)
|
||||
*/
|
||||
EVT_BUTTON(wxID_OK, MainFrame::OnButtonOK)
|
||||
END_EVENT_TABLE()
|
||||
#endif
|
||||
|
||||
bool MyApp::OnInit()
|
||||
{
|
||||
MainFrame* frame = new MainFrame(wxT("Minimal wxWidgets App"));
|
||||
frame->Show(true);
|
||||
|
||||
#ifdef USE_DYNAMIC_CONNECT
|
||||
/*
|
||||
三个参数分别为菜单标识符,事件标识符和事件处理函数指针。要注意这里的事件标
|
||||
识符 wxEVT_COMMAND_MENU_SELECTED不同于前面在静态事件表中用于表示事件映射的宏EVT_MENU,实
|
||||
际上EVT_MENU内部也使用了wxEVT_COMMAND_MENU_SELECTED.EVT_MENU其实也自动包含了用于对事
|
||||
件处理指针类型强制转换的宏 wxCommandEventHandler()。一般说来,如果事件处理函数的参数类型是
|
||||
wxXYZEvent,那么其处理函数的类型就应该用 wxXYZEventHandler宏进行强制转换.
|
||||
|
||||
有对应的 frame->Disconnect
|
||||
*/
|
||||
frame->Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
|
||||
wxCommandEventHandler(MainFrame::OnQuit));
|
||||
frame->Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
|
||||
wxCommandEventHandler(MainFrame::OnAbout));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -33,10 +52,7 @@ void MainFrame::OnAbout(wxCommandEvent& event)
|
||||
wxMessageBox(msg, wxT("About Minimal"), wxOK | wxICON_INFORMATION, this);
|
||||
}
|
||||
|
||||
void MainFrame::OnQuit(wxCommandEvent& event)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
void MainFrame::OnQuit(wxCommandEvent& event) { Close(); }
|
||||
|
||||
MainFrame::MainFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title)
|
||||
{
|
||||
@ -56,37 +72,37 @@ MainFrame::MainFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title)
|
||||
// ...然后将菜单条放置在主窗口上
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
wxButton* button = new wxButton(this, wxID_OK, wxT("OK"),
|
||||
wxPoint(200, 200));
|
||||
wxButton* button =
|
||||
new wxButton(this, wxID_OK, wxT("OK"), wxPoint(200, 200));
|
||||
|
||||
CreateStatusBar(2);
|
||||
SetStatusText(wxT("Welcome to wxWidgets!"));
|
||||
}
|
||||
|
||||
void MainFrame::OnSize(wxSizeEvent& event)
|
||||
{
|
||||
|
||||
}
|
||||
void MainFrame::OnSize(wxSizeEvent& event) {}
|
||||
|
||||
void MainFrame::OnButtonOK(wxCommandEvent& event)
|
||||
{
|
||||
/*
|
||||
当用户点击了确认按钮的时候,一个新的wxCommandEvent事件被创建,其中包
|
||||
含标识符wxID_OK和事件类型 wxEVT_COMMAND_BUTTON_CLICKED,然后这个按钮的事件表开始通过
|
||||
wxEvtHandler::ProcessEvent函数进行匹配,事件表中的每一个条目都会去尝试匹配,然后是其父类wxControl
|
||||
的事件表,然后是wxWindow的。如果都没有匹配到, wxWidgets会搜索其父亲的类事件表,然后就找到了一
|
||||
条匹配条目:EVT_BUTTON(wxID_OK,MyFrame::OnButtonOK)
|
||||
/*
|
||||
当用户点击了确认按钮的时候,一个新的wxCommandEvent事件被创建,其中包
|
||||
含标识符wxID_OK和事件类型
|
||||
wxEVT_COMMAND_BUTTON_CLICKED,然后这个按钮的事件表开始通过
|
||||
wxEvtHandler::ProcessEvent函数进行匹配,事件表中的每一个条目都会去尝试匹配,然后是其父类wxControl
|
||||
的事件表,然后是wxWindow的。如果都没有匹配到,
|
||||
wxWidgets会搜索其父亲的类事件表,然后就找到了一
|
||||
条匹配条目:EVT_BUTTON(wxID_OK,MyFrame::OnButtonOK)
|
||||
|
||||
简单来讲就是:先匹配自己的处理事件函数(若有继承往上找),没有去父类找。
|
||||
简单来讲就是:先匹配自己的处理事件函数(若有继承往上找),没有去父类找。
|
||||
|
||||
只有Command事件(其事件类型直接或者间接的继承自wxCommandEvent)才会被递归的应用
|
||||
到其父亲的事件表。通常这是wxWidgets的用户经常会感到困惑的地方,因此我们把那些不会传递给其父亲的事
|
||||
件表的事件列举如下:wxActivate, wxCloseEvent, wxEraseEvent, wxFocusEvent, wxKeyEvent, wxIdleEvent,
|
||||
wxInitDialogEvent, wxJoystickEvent, wxMenuEvent, wxMouseEvent, wxMoveEvent, wxPaintEvent,
|
||||
wxQueryLayoutInfoEvent, wxSizeEvent, wxScrollWinEvent, 和wxSysColourChangedEvent,这些事件都不
|
||||
会传给事件源控件的父亲.
|
||||
这些事件不会传递给其父亲,是因为这些事件仅对产生这个事件的窗口才有意义,举例来说,把一个子窗口的重
|
||||
绘事件发送给它的父亲,其实是没有任何意义的。
|
||||
只有Command事件(其事件类型直接或者间接的继承自wxCommandEvent)才会被递归的应用
|
||||
到其父亲的事件表。通常这是wxWidgets的用户经常会感到困惑的地方,因此我们把那些不会传递给其父亲的事
|
||||
件表的事件列举如下:wxActivate, wxCloseEvent, wxEraseEvent,
|
||||
wxFocusEvent, wxKeyEvent, wxIdleEvent, wxInitDialogEvent,
|
||||
wxJoystickEvent, wxMenuEvent, wxMouseEvent, wxMoveEvent, wxPaintEvent,
|
||||
wxQueryLayoutInfoEvent, wxSizeEvent, wxScrollWinEvent,
|
||||
和wxSysColourChangedEvent,这些事件都不 会传给事件源控件的父亲.
|
||||
这些事件不会传递给其父亲,是因为这些事件仅对产生这个事件的窗口才有意义,举例来说,把一个子窗口的重
|
||||
绘事件发送给它的父亲,其实是没有任何意义的。
|
||||
|
||||
*/
|
||||
*/
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "wx/wx.h"
|
||||
|
||||
#define USE_DYNAMIC_CONNECT
|
||||
|
||||
/*
|
||||
应用程序一直停留在一个循环中,等待着来自用户或者其他地方
|
||||
(比如窗口刷新或网络连接)的事件,一旦收到某种事件,应用程序就将其扔给处理这个事件的函数。虽然看上
|
||||
@ -66,6 +68,37 @@
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
挂载事件表:
|
||||
你并不一定非要实现继承自某个类的新类,才可以改变它的事件表。对于那些继承自wxWindow的类来说,有另
|
||||
外一种可取代的方法。你可以通过实现一个新的直接继承自wxEvtHandler的新类,然后定义这个新类事件表,然
|
||||
后使用wxWindow::PushEventHandler函数将这个事件表压入到某个窗口类的事件表栈中。最后压入的那个事件
|
||||
表在事件匹配过程中将会被最先匹配,如果在其中没有匹配到对应的事件处理过程,那么栈中以前的事件表仍将
|
||||
被匹配,如此类推。你还可以用wxWindow::PopEventHandler函数来弹出最顶层的事件表,如果你给
|
||||
wxWindow:: PopEventHandler函数传递的是True的参数,那么这个弹出的事件表将被删除。
|
||||
这种方法可以避免大量的类重载,也使不同的类的实例共享同一个事件表成为可能。
|
||||
有时候,你需要手动调用窗口类的事件表,这时候你应该使用wxWindow::GetEventHandler方法,而不是直接
|
||||
使用调用这个窗口类的成员函数。虽然wxWindow::GetEventHandler通常返回这个窗口类本身。但是如果你之
|
||||
前曾经使用 PushEventHandler压入另外一个事件表,那么函数将会返回处于最顶层的事件表。因此使用
|
||||
wxWindow:: GetEventHandler函数才可以保证事件被正确的处理。
|
||||
PushEventHandler的方法通常用来临时的或者永久的改变图形界面的行为。举例来说,加入你想在你的应用程
|
||||
序实现对话框编辑的功能。你可以捕获这个对话框和它的内部控件的所有的鼠标事件,先使用你自己的事件表处
|
||||
理这些事件,来进行类似拖拽控件,改变控件大小以及移动控件动作。这在联机教学中也是很有用技术。你可以
|
||||
在你自己的事件表中过滤收到的事件,如果是可以接受的,则调用wxEvent::Skip函数正常处理。
|
||||
*/
|
||||
|
||||
/*
|
||||
动态事件处理
|
||||
前面我们讨论的事件处理方法,都是静态的事件表,这也是我们处理事件最常用的方式。接下来,我们来讨论一
|
||||
下事件表的动态处理,也就是说在运行期改变事件表的映射关系。使用这种事件映射方法的原因,可能是你想在
|
||||
程序运行的不同时刻使用不同的映射关系,或者因为你使用的那种语言(例如python)不支持静态映射,或者仅仅
|
||||
是因为你更喜欢动态映射。因为动态映射的方法可以使你更精确的控制事件表的细节,你甚至可以单独的将事件
|
||||
表中的某一个条目在运行期打开或者关闭,而前面说的PushEventHandler和PopEventHandler的方法只能针对
|
||||
整个事件表进行处理。除此以外,动态事件处理还允许你在不同的类之间共享事件函数。
|
||||
和动态事件处理相关的API有两个:wxEvtHandler::Connect和wxEvtHandler::Disconnect。大多数情况下你不需
|
||||
要手动调用wxEvtHandler::Disconnect函数,这个函数将在窗口类被释放的时候自动。
|
||||
*/
|
||||
|
||||
class MyApp : public wxApp {
|
||||
public:
|
||||
virtual bool OnInit();
|
||||
|
Loading…
x
Reference in New Issue
Block a user