Ubuntu下的wxWidgets事件驱动

1事件驱动编程

所有的GUI程序都是事件驱动的。也就是说,应用程序一直停留在一个循环中,等待来自用户或其它地方的事件,一旦接收到某个事件,就将它交给某个事件函数进行处理。虽然看上去不同的窗口是同时被刷新的,但实际上,绝大多数的GUI程序都是单线程的,因此窗口的刷新是按顺寻进行的。

WxWidgets事件由三部分来描述:

1 Event Type:标示事件类型(wxEventType)的唯一值。

2 Event Class:它是一个wxEvent的派生类。该类对象附带了事件的相关信息。

3 Event Source:wxEvent存储了产生事件的对象和它的标示符。这是事件系统中唯一确定事件产生源(窗口)的整数。不同的窗体可能会产生相同类型的事件,通过窗口标示符可以对它们加以区分。

2 事件表和事件处理过程

wxWidgets事件处理系统比起通常的虚方法机制说要稍微复杂一些,但它的一个好处是可以避免实现基类中所有的虚方法,因为实现所有的虚方法有时候是不切实际或者是低效率的。

每一个wxEvtHandler的派生类,例如Frame,按钮,菜单等,都会在其内部维护一个事件表,用来告诉wxWidgets事件和事件处理过程的对应关系。所有继承自wxWindows的窗口类以及应用程序都是wxEvtHandler的派生类。

3 动态事件表的加载

静态事件表是我们处理事件最常用也是比较简单的方式。但有的时候我们希望在程序运行的不同时间使用不同的映射关系,或者你更喜欢使用可以精确控制的事件,甚至是你希望在不同的类之间共享事件函数,这就需要动态事件映射的方法。


voidwxEvtHandler::Connect (int id,

 int   last id, 

 wxEventType eventType,  

 wxObjectEventFunction function, 

 wxObject *userData=NULL, 

 wxEvtHandler *eventSink=NULL)

Connects the given function dynamically with the event handler, id andevent type. 

voidwxEvtHandler::Connect (int id,

 wxEventType eventType,  

 wxObjectEventFunction function, 

 wxObject *userData=NULL, 

 wxEvtHandler *eventSink=NULL)

This overload can be used to attach an event handler to a single source ID.


voidwxEvtHandler::Connect (int id, wxObjectEventFunction function, 

 wxObject *userData=NULL, 

 wxEvtHandler *eventSink=NULL)

This overload will connect the given event handler so that regardless ofthe ID of the event source, the handler will be called.

Disconnect (wxEventType eventType,   wxObjectEventFunction function, 

 wxObject *userData=NULL, 

 wxEvtHandler *eventSink=NULL);

Disconnect (int id=wxID_ANY

 wxEventType eventType=wxEVT_NULL,   wxObjectEventFunction function=NULL, 

 wxObject *userData=NULL, 

 wxEvtHandler *eventSink=NULL);

Disconnect (int id, intlastId

 wxEventType eventType,   wxObjectEventFunction function=NULL, 

 wxObject *userData=NULL, 

 wxEvtHandler *eventSink=NULL);


Bind (constEventTag &eventType,   Functorfunctor,

 int id=wxID_ANY,

 intlastId=wxID_ANY,

 wxObject *userData=NULL)

该函数在功能上和Connect函数相同,但是它用任意函数处理事件,而Connect函数只能够使用wxEvtHandler的派生类函数。

4 自定义事件

每一个事件都是由事件类型(wxEventType)唯一确定的,所以在自定义事件的时候,首先应该定义一个新的事件类型。

wxDEFINE_EVENT()

wxDECLARE_EVENT()

然后确定我们要使用的是已经存在的事件类定义还是定义全新事件。

最后是产生事件和传递事件。所谓产生事件就是实例化事件类,即声明一个事件类对象并初始化。而传递消息就是处理消息的过程。


4.1使用已经存在的事件类

wxDECLARE_EVENT(name,cls)

//cls是一个已存在的wxEvent(派生)类。

定义静态事件表

事件处理


// this is typically in a header: it just declares MY_EVENT event type

wxDECLARE_EVENT(MY_EVENT,wxCommandEvent);

// this is a definition so can't be in a header

wxDEFINE_EVENT(MY_EVENT,wxCommandEvent);

// example of code handling the event with event tables

wxBEGIN_EVENT_TABLE(MyFrame,wxFrame)

EVT_MENU (wxID_EXIT, MyFrame::OnExit)

...

EVT_COMMAND (ID_MY_WINDOW, MY_EVENT, MyFrame::OnMyEvent)

wxEND_EVENT_TABLE()

void MyFrame::OnMyEvent(wxCommandEvent& event)

{

  // do something

}


// example of code handling the event with Bind<>():

MyFrame::MyFrame()

{

Bind(MY_EVENT, &MyFrame::OnMyEvent, this, ID_MY_WINDOW);

}

// example of code generating the event

void MyWindow::SendEvent()

{

  wxCommandEvent event(MY_EVENT,GetId());

  event.SetEventObject(this);

  // Give it some contents

  event.SetString("Hello");

  // Do send it

  ProcessWindowEvent(event);

}


#include "MyEvent.h"

MyEvent::MyEvent(wxEventTypeeventType,intwinid, constwxString& info)

    :wxEvent(winid,eventType)

{

   myinfo = info;

}

voidMyEvent::SetInfo(constwxString info)

{

   myinfo = info;

}

wxStringMyEvent::GetInfo()

{

    returnmyinfo;

}

wxEvent*MyEvent::Clone() const

{

    return newMyEvent(*this);

}


4.2 定义全新事件

1 定义新的事件类

#include <wx/event.h>

class MyEvent : public wxEvent

{

    public:

        MyEvent(wxEventType eventType, int winid, const wxString& info = NULL);

        void SetInfo(const wxString info);

        wxString GetInfo();

        virtual wxEvent* Clone() const;

    protected:

    private:

        wxString myinfo;

};


2 定义新的事件类型

wxDEFINE_EVENT

(MY_EVENT_TYPE, MyEvent);

3-1 静态事件处理机制

#define MyEventHandler(func) (&func)

#define EVT_MINE(id, func)

wx__DECLARE_EVT1(

  MY_EVENT_TYPE,

  id,  

  MyEventHandler(func))

定义事件表

BEGIN_EVENT_TABLE(MyEvtFrame, wxFrame)

  …

  EVT_MINE(idMyEvt,MyEvtFrame::OnMyEvent)

  …

END_EVENT_TABLE()

3-2 动态事件加载

如果我们使用Bind<>方法,则勿需以上步骤,可以直接绑定事件到任意事件处理函数。

Bind(MY_EVENT_TYPE,    &MyEvtFrame::OnMyEvent,

  this,

  idMyEvt);

4 处理事件

   MyEvent myevent(MY_EVENT_TYPE,   idMyEvt, _("This is my event!"));

          myevent.SetEventObject(this);

          ProcessWindowEvent(myevent);

5 事件的传播

有两种类型的事件:Basic EventCommand Event。它们的区别在于传播方式。Command Event可以从子控件到父控件传递,而Basic Event则不可以。

6 窗口标示符

Window identifiers are integers that uniquely determine the window identityin the event system. There are three ways to create window id's.

ület the system automatically create an id
üuse standard identifiers
ücreate your own id

7 Event Handlersvs Virtual Methods






posted @ 2014-04-16 10:54  ZhangAihua  阅读(289)  评论(0编辑  收藏  举报