动态事件处理方法
This commit is contained in:
parent
fc53babbb8
commit
d07cc4295e
@ -1,5 +1,7 @@
|
|||||||
#include "event_demo.h"
|
#include "event_demo.h"
|
||||||
|
|
||||||
|
#ifndef USE_DYNAMIC_CONNECT
|
||||||
|
// 静态链接
|
||||||
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
||||||
EVT_MENU(wxID_ABOUT, MainFrame::OnAbout)
|
EVT_MENU(wxID_ABOUT, MainFrame::OnAbout)
|
||||||
EVT_MENU(wxID_EXIT, MainFrame::OnQuit)
|
EVT_MENU(wxID_EXIT, MainFrame::OnQuit)
|
||||||
@ -18,11 +20,28 @@ EVT_SIZE(MainFrame::OnSize)
|
|||||||
*/
|
*/
|
||||||
EVT_BUTTON(wxID_OK, MainFrame::OnButtonOK)
|
EVT_BUTTON(wxID_OK, MainFrame::OnButtonOK)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
#endif
|
||||||
|
|
||||||
bool MyApp::OnInit()
|
bool MyApp::OnInit()
|
||||||
{
|
{
|
||||||
MainFrame* frame = new MainFrame(wxT("Minimal wxWidgets App"));
|
MainFrame* frame = new MainFrame(wxT("Minimal wxWidgets App"));
|
||||||
frame->Show(true);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,10 +52,7 @@ void MainFrame::OnAbout(wxCommandEvent& event)
|
|||||||
wxMessageBox(msg, wxT("About Minimal"), wxOK | wxICON_INFORMATION, this);
|
wxMessageBox(msg, wxT("About Minimal"), wxOK | wxICON_INFORMATION, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnQuit(wxCommandEvent& event)
|
void MainFrame::OnQuit(wxCommandEvent& event) { Close(); }
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
MainFrame::MainFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title)
|
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);
|
SetMenuBar(menuBar);
|
||||||
|
|
||||||
wxButton* button = new wxButton(this, wxID_OK, wxT("OK"),
|
wxButton* button =
|
||||||
wxPoint(200, 200));
|
new wxButton(this, wxID_OK, wxT("OK"), wxPoint(200, 200));
|
||||||
|
|
||||||
CreateStatusBar(2);
|
CreateStatusBar(2);
|
||||||
SetStatusText(wxT("Welcome to wxWidgets!"));
|
SetStatusText(wxT("Welcome to wxWidgets!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnSize(wxSizeEvent& event)
|
void MainFrame::OnSize(wxSizeEvent& event) {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainFrame::OnButtonOK(wxCommandEvent& event)
|
void MainFrame::OnButtonOK(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
当用户点击了确认按钮的时候,一个新的wxCommandEvent事件被创建,其中包
|
当用户点击了确认按钮的时候,一个新的wxCommandEvent事件被创建,其中包
|
||||||
含标识符wxID_OK和事件类型 wxEVT_COMMAND_BUTTON_CLICKED,然后这个按钮的事件表开始通过
|
含标识符wxID_OK和事件类型
|
||||||
wxEvtHandler::ProcessEvent函数进行匹配,事件表中的每一个条目都会去尝试匹配,然后是其父类wxControl
|
wxEVT_COMMAND_BUTTON_CLICKED,然后这个按钮的事件表开始通过
|
||||||
的事件表,然后是wxWindow的。如果都没有匹配到, wxWidgets会搜索其父亲的类事件表,然后就找到了一
|
wxEvtHandler::ProcessEvent函数进行匹配,事件表中的每一个条目都会去尝试匹配,然后是其父类wxControl
|
||||||
条匹配条目:EVT_BUTTON(wxID_OK,MyFrame::OnButtonOK)
|
的事件表,然后是wxWindow的。如果都没有匹配到,
|
||||||
|
wxWidgets会搜索其父亲的类事件表,然后就找到了一
|
||||||
|
条匹配条目:EVT_BUTTON(wxID_OK,MyFrame::OnButtonOK)
|
||||||
|
|
||||||
简单来讲就是:先匹配自己的处理事件函数(若有继承往上找),没有去父类找。
|
简单来讲就是:先匹配自己的处理事件函数(若有继承往上找),没有去父类找。
|
||||||
|
|
||||||
只有Command事件(其事件类型直接或者间接的继承自wxCommandEvent)才会被递归的应用
|
只有Command事件(其事件类型直接或者间接的继承自wxCommandEvent)才会被递归的应用
|
||||||
到其父亲的事件表。通常这是wxWidgets的用户经常会感到困惑的地方,因此我们把那些不会传递给其父亲的事
|
到其父亲的事件表。通常这是wxWidgets的用户经常会感到困惑的地方,因此我们把那些不会传递给其父亲的事
|
||||||
件表的事件列举如下:wxActivate, wxCloseEvent, wxEraseEvent, wxFocusEvent, wxKeyEvent, wxIdleEvent,
|
件表的事件列举如下:wxActivate, wxCloseEvent, wxEraseEvent,
|
||||||
wxInitDialogEvent, wxJoystickEvent, wxMenuEvent, wxMouseEvent, wxMoveEvent, wxPaintEvent,
|
wxFocusEvent, wxKeyEvent, wxIdleEvent, wxInitDialogEvent,
|
||||||
wxQueryLayoutInfoEvent, wxSizeEvent, wxScrollWinEvent, 和wxSysColourChangedEvent,这些事件都不
|
wxJoystickEvent, wxMenuEvent, wxMouseEvent, wxMoveEvent, wxPaintEvent,
|
||||||
会传给事件源控件的父亲.
|
wxQueryLayoutInfoEvent, wxSizeEvent, wxScrollWinEvent,
|
||||||
这些事件不会传递给其父亲,是因为这些事件仅对产生这个事件的窗口才有意义,举例来说,把一个子窗口的重
|
和wxSysColourChangedEvent,这些事件都不 会传给事件源控件的父亲.
|
||||||
绘事件发送给它的父亲,其实是没有任何意义的。
|
这些事件不会传递给其父亲,是因为这些事件仅对产生这个事件的窗口才有意义,举例来说,把一个子窗口的重
|
||||||
|
绘事件发送给它的父亲,其实是没有任何意义的。
|
||||||
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "wx/wx.h"
|
#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 {
|
class MyApp : public wxApp {
|
||||||
public:
|
public:
|
||||||
virtual bool OnInit();
|
virtual bool OnInit();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user