使用模板化自定义wxEvent和wxEvtHandler :: Bind

时间:2010-10-26 22:15:35

标签: c++ events wxwidgets

在以下代码中,我执行以下操作:

  • 我创建了一个新模板wxCommandEvent类,它包含模板指定的一些有效负载。
  • 然后我继承了一个wxStringPayloadEvent类。
  • 最后,我创建了一个示例应用程序,只需发出一个wxStringPayloadEvent,然后触发事件处理程序并在屏幕上的消息框中显示有效负载。

如果我使用稍微老式的wxEvtHandler :: Connect方法(正如我在下面评论过的那样),那么一切正常。但是如果我使用wxEvtHandler :: Bind方法,我会得到一系列非常神秘的错误消息(在代码之后发布)。

由于Bind允许更多自由并且更容易使用(它不需要创建笨拙的宏),那么我想用它而不是Connect ...任何想法?

以下是代码:

#include <wx/wx.h>

//Creating my own custom event which will hold a payload of some templated type
template <class Payload_type>
class TemplatedPayloadEvent : public wxCommandEvent
{
public:
 TemplatedPayloadEvent(){}
 TemplatedPayloadEvent(wxEventType eventType) : wxCommandEvent(eventType){}

 TemplatedPayloadEvent(const TemplatedPayloadEvent& event)
 : wxCommandEvent(event)  
 {
  this->mPayload = event.mPayload;
 }

 virtual TemplatedPayloadEvent* Clone() const {return new TemplatedPayloadEvent(*this);}

 void setPayload(Payload_type payload) {mPayload = payload;}
 Payload_type getPayload() {return mPayload;}

private:
 Payload_type mPayload;
};


//instantiating new event along with associated elements
class wxStringPayloadEvent : public TemplatedPayloadEvent<wxString>
{
public:
 wxStringPayloadEvent() : TemplatedPayloadEvent<wxString>(wxEVT_STRING_PAYLOAD){};
};
typedef void (wxEvtHandler::*wxStringPayloadEventFunction)(wxStringPayloadEvent&);
#define wxStringPayloadEventHandler(func) \
 (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)\
 wxStaticCastEvent(wxStringPayloadEventFunction, &func)
const wxEventType wxEVT_STRING_PAYLOAD = wxNewEventType();


//implementing test application
class MyApp : public wxApp
{
public:
 virtual bool OnInit();
 void OnProcessCustom(wxStringPayloadEvent& event);
};

bool
MyApp::OnInit()
{
 //Connect event
 //Connect(wxEVT_STRING_PAYLOAD, wxStringPayloadEventHandler(MyApp::OnProcessCustom));
 Bind(wxEVT_STRING_PAYLOAD, &MyApp::OnProcessCustom, this);///< wish I could use this

    wxStringPayloadEvent eventCustom;
 eventCustom.SetEventObject(this);
 eventCustom.setPayload(wxT("Test payload."));
 wxPostEvent(this, eventCustom);

 return true;
}

void MyApp::OnProcessCustom(wxStringPayloadEvent& event)
{
 wxMessageBox(wxT("Event received.  Payload = \"") + event.getPayload() + wxT("\""));
}

IMPLEMENT_APP(MyApp);

以下是错误消息:

/ThirdParty/Includes/wx/event.h: In constructor 'wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler>::wxEventFunctorMethod(void (Class::*)(EventArg&), EventHandler*) [with EventTag = int, Class = MyApp, EventArg = wxStringPayloadEvent, EventHandler = MyApp]':
/ThirdParty/Includes/wx/event.h:587:   instantiated from 'wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler>* wxNewEventFunctor(const EventTag&, void (Class::*)(EventArg&), EventHandler*) [with EventTag = int, Class = MyApp, EventArg = wxStringPayloadEvent, EventHandler = MyApp]'
/ThirdParty/Includes/wx/event.h:3182:   instantiated from 'void wxEvtHandler::Bind(const EventTag&, void (Class::*)(EventArg&), EventHandler*, int, int, wxObject*) [with EventTag = wxEventType, Class = MyApp, EventArg = wxStringPayloadEvent, EventHandler = MyApp]'
../src/program.cpp:29:   instantiated from here
/ThirdParty/Includes/wx/event.h:382: error: invalid conversion from 'wxEvent*' to 'wxStringPayloadEvent*'
/ThirdParty/Includes/wx/event.h:382: error:   initializing argument 1 of 'static void wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler>::CheckHandlerArgument(EventArg*) [with EventTag = int, Class = MyApp, EventArg = wxStringPayloadEvent, EventHandler = MyApp]'

更新更多线索:

  • This might be a clue,但我的C ++仍然不够好,无法确定。
  • 查看event.h:382我发现以下评论:
  

如果你在这里得到一个错误,这意味着你试图使用的处理程序的签名与用于此事件类型的真实事件类不兼容(即,与其基本类不同) / p>

1 个答案:

答案 0 :(得分:1)

这可能是应该记录的内容,但据我所知,当你使用Bind()时,你不能只使用'const wxEventType ...'来声明你的事件类型。 Bind()需要使用wxDEFINE_EVENT()时提供的事件类型类。所以,你实际上需要在这里做一些改变。

1)使用它来定义事件类型(替换'const wxEventType ...'):

wxDEFINE_EVENT(wxEVT_STRING_PAYLOAD, wxStringPayloadEvent);

2)上面需要在明确定义wxStringPayloadEvent之后完成,因此你的wxStringPayloadEvent构造函数不能默认为你的自定义事件类型。所以这里是wxStringPayloadEvent的构造函数看起来应该更像:

wxStringPayloadEvent() : TemplatedPayloadEvent<wxString>(){};
wxStringPayloadEvent(wxEventType eventType) : TemplatedPayloadEvent<wxString>(eventType){};

3)由于您无法默认事件类型,因此您需要在自定义事件对象构造中指定它:

wxStringPayloadEvent eventCustom(wxEVT_STRING_PAYLOAD);

我已经用SVN中继测试了这些变化,它看起来效果很好。