Reputation: 53
Using wxwidgets in C++, I am trying to bind an event in one class to functions in different classes. Here is a minimal reproducable example:
#include <wx/wx.h>
#include <wx/notebook.h>
#include <wx/panel.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
IMPLEMENT_APP(MyApp)
class Notebook : public wxFrame
{
public:
Notebook(const wxString& title);
};
class MyPanelA : public wxPanel
{
public:
MyPanelA(wxNotebook* parent);
void FuncA(wxCommandEvent& event);
};
class MyPanelB : public wxPanel
{
public:
MyPanelB(wxNotebook* parent);
void FuncB(wxCommandEvent& event);
};
bool MyApp::OnInit()
{
Notebook* notebook = new Notebook(wxT("Notebook"));
notebook->Show(true);
return true;
}
Notebook::Notebook(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(400, 350))
{
wxNotebook* nb = new wxNotebook(this, -1, wxPoint(-1, -1),
wxSize(-1, -1), wxNB_BOTTOM);
MyPanelA* panel1 = new MyPanelA(nb);
MyPanelB* panel2 = new MyPanelB(nb);
nb->AddPage(panel1, wxT("Sheet1"));
nb->AddPage(panel2, wxT("Sheet2"));
CreateStatusBar();
Center();
}
MyPanelA::MyPanelA(wxNotebook* parent)
: wxPanel(parent, wxID_ANY)
{
wxButton* Button1 = new wxButton(this, wxID_ANY, wxT("Button A"));
Button1->Bind(wxEVT_BUTTON, &MyPanelA::FuncA, this, wxID_ANY);
//Button1->Bind(wxEVT_BUTTON, &MyPanelB::FuncB, this, wxID_ANY);
}
MyPanelB::MyPanelB(wxNotebook* parent)
: wxPanel(parent, wxID_ANY)
{
wxButton* Button2 = new wxButton(this, wxID_ANY, wxT("Button B"));
Button2->Bind(wxEVT_BUTTON, &MyPanelB::FuncB, this, wxID_ANY);
//Button2->Bind(wxEVT_BUTTON, &MyPanelA::FuncA, this, wxID_ANY);
}
void MyPanelA::FuncA(wxCommandEvent& event)
{
wxMessageBox("This is Func A");
}
void MyPanelB::FuncB(wxCommandEvent& event)
{
wxMessageBox("This is Func B");
}
The problem occurs in the functions MyPanelA::MyPanelA(wxNotebook* parent)
and MyPanelB::MyPanelB(wxNotebook* parent)
. Lets focus on the first. If I use the binding line Button1->Bind(wxEVT_BUTTON, &MyPanelA::FuncA, this, wxID_ANY)
as is currently in the code above, everything works just fine. But if I use instead the following commented line Button1->Bind(wxEVT_BUTTON, &MyPanelB::FuncB, this, wxID_ANY)
which referes to the function in PanelB, I get an compiler error 'cannot convert argument 1 from 'EventHandler* const' to 'T *'.
I'm not sure what this error means, but I've got a feeling I'm not sending the correct object, and that I should be using something other than 'this'. Is this true? If so, what object should I be using and how can I find it?
Upvotes: 0
Views: 120
Reputation: 22753
(updated answer after the source code has been provided)
You're trying to pass this
, which is MyPanelB*
, as the pointer to call MyPanelA::FuncA()
on. This obviously (and luckily) doesn't compile as calling a member function of a class on an object of a different class could never work.
I'm not sure what exactly you're trying to do, but it goes without saying that you need to pass the object pointer matching the class of the member function you want to bind.
I.e. in this case, Bind()
needs the an object instance of type MyPanelB
to call the handler FuncB
on. Using this
, which is MyPanelA
, is wrong.
Here is a working example
#include <wx/wx.h>
#include <wx/notebook.h>
#include <wx/panel.h>
class MyApp : public wxApp
{
public:
bool OnInit() override;
};
wxIMPLEMENT_APP(MyApp);
class NotebookFrame : public wxFrame
{
public:
explicit NotebookFrame(const wxString& title);
};
class MyPanelA : public wxPanel
{
public:
MyPanelA(wxNotebook* parent, class MyPanelB* panelB);
void FuncA(wxCommandEvent& event);
private:
MyPanelB* m_panelB; // To store reference to MyPanelB
};
class MyPanelB : public wxPanel
{
public:
explicit MyPanelB(wxNotebook* parent);
void FuncB(wxCommandEvent& event);
};
bool MyApp::OnInit()
{
NotebookFrame* notebook = new NotebookFrame("NotebookFrame");
notebook->Show(true);
return true;
}
NotebookFrame::NotebookFrame(const wxString& title)
: wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxSize(400, 350))
{
wxNotebook* nb = new wxNotebook(this, wxID_ANY);
MyPanelB* panel2 = new MyPanelB(nb); // Create PanelB first
MyPanelA* panel1 = new MyPanelA(nb, panel2); // Pass PanelB to PanelA
nb->AddPage(panel1, "Sheet1");
nb->AddPage(panel2, "Sheet2");
}
MyPanelA::MyPanelA(wxNotebook* parent, MyPanelB* panelB)
: wxPanel(parent, wxID_ANY), m_panelB(panelB) // Store reference to PanelB
{
wxButton* Button1 = new wxButton(this, wxID_ANY, "Button A");
Button1->Bind(wxEVT_BUTTON, &MyPanelB::FuncB, m_panelB, wxID_ANY); // Bind to FuncB in PanelB
}
MyPanelB::MyPanelB(wxNotebook* parent)
: wxPanel(parent, wxID_ANY)
{
wxButton* Button2 = new wxButton(this, wxID_ANY, "Button B");
Button2->Bind(wxEVT_BUTTON, &MyPanelB::FuncB, this, wxID_ANY);
}
void MyPanelA::FuncA(wxCommandEvent& event)
{
wxMessageBox("This is Func A");
}
void MyPanelB::FuncB(wxCommandEvent& event)
{
wxMessageBox("This is Func B");
}
Upvotes: 0