Использование шаблонного пользовательского wxEvent с wxEvtHandler :: Bind - PullRequest
1 голос
/ 27 октября 2010

В следующем коде я делаю следующее:

  • Я создаю новый шаблонный класс 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]'

Обновление больше подсказок:

  • Это может быть подсказка, , но мой C ++ все еще недостаточно хорош, чтобы быть уверенным.
  • Глядя на event.h: 382, ​​я нахожу следующий комментарий:

если вы получаете здесь ошибку, это означает, что подпись обработчика, который вы пытаетесь использовать, не совместима (т.е. не совпадает с базовым классом или с ним) реального класса события, используемого для этого типа события

1 Ответ

1 голос
/ 29 октября 2010

Это, вероятно, что-то, что должно быть задокументировано, но, насколько я вижу, вы не можете просто объявить свой тип события, используя 'const wxEventType ...', когда вы используете Bind ().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, и, кажется, она прекрасно работает.

...