将模板化自定义 wxEvent 与 wxEvtHandler::Bind 一起使用

发布于 2024-09-29 09:36:50 字数 4050 浏览 6 评论 0原文

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

  • 我创建一个新的模板 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]'

更新更多线索:

如果您在此处收到错误,则意味着您尝试使用的处理程序的签名与用于此事件类型的真实事件类不兼容(即与其基类不同)< /p>

In the following code I do the following:

  • I create a new template wxCommandEvent class that holds some payload specified by the template.
  • I then subclass a wxStringPayloadEvent class.
  • Finally I create an example app that simply issues a wxStringPayloadEvent and then the event handler gets triggered and displays the payload in a message box on the screen.

If I use the slightly old-fashioned wxEvtHandler::Connect method, (as I've commented out below), then everything works. But if I use the wxEvtHandler::Bind method I get a series of very cryptic error messages (posted after the code).

Since Bind allows more freedom and is easier to use (it doesn't require creating awkward macros), then I would like to use it instead of Connect ... any ideas?

Here's the code:

#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);

Here's the error message:

/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]'

Update more clues:

  • This might be a clue, but my C++ is still not good enough to be sure.
  • Looking at event.h:382 I find the following comment:

if you get an error here it means that the signature of the handler you're trying to use is not compatible with (i.e. is not the same as or a base class of) the real event class used for this event type

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

亚希 2024-10-06 09:36:50

这可能是应该记录的内容,但据我所知,当您使用 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 trunk 测试了这些更改,而且看起来效果很好。

This is probably something that should be documented, but as far as I can see, you can't just declare your event type using 'const wxEventType ...' when you're using Bind(). Bind() requires the event type class which is provided when you use wxDEFINE_EVENT() instead. So, you actually need to make a few changes here.

1) Use this to define your event type (replacing 'const wxEventType ...'):

wxDEFINE_EVENT(wxEVT_STRING_PAYLOAD, wxStringPayloadEvent);

2) The above needs to be done after wxStringPayloadEvent has been defined obviously, so your wxStringPayloadEvent constructors can't just default to your custom event type. So here's what you're constructors for wxStringPayloadEvent should look more like:

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

3) Since you can't default your event type, you'll need to specify it in your custom event object construction:

wxStringPayloadEvent eventCustom(wxEVT_STRING_PAYLOAD);

I've tested these changes with SVN trunk, and it seems to work beautifully.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文