I am a novice in C++ and wxWidgets, and use wxFormBuilder to help me create the GUI.
I like the idea to put similar functions together in 1 module, which means that my apps have multiple modules. One of the modules is for the GUI (it now contains code for the main Frame (with only a menu and taskbar) and a Panel (with 2 StaticText controls and a button). The button increments a counter and the value is shown in one of the StaticTexts on the Panel.
Sofar so good. (compiles without errors) I can make the Panel show/Hide, but I seem to miss an essential piece of knowledge to make the Panel button work. The ways I tried are all similar to the way the Main module is coded, but that is not working.
I understand how it works with GUI class elements in the same file. However, I like to keep all GUI code in one module (GUIFrame.h/.cpp), and all the 'function' code in e.g. the Panel module (MyPanel.h/.cpp).
Just because I am not sure where I make my mistake, I present all code in this post. My aplologies if it is too much.
Hopefully someone can help me bridge my gap in knowledge about this way of working.
Regards, Ruud
=== GUIFrame.h
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/string.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/menu.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/statusbr.h>
#include <wx/frame.h>
#include <wx/stattext.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/panel.h>
///////////////////////////////////////////////////////////////////////////
#define idMenuQuit 1000
///////////////////////////////////////////////////////////////////////////////
/// Class GUIFrame
///////////////////////////////////////////////////////////////////////////////
class GUIFrame : public wxFrame
{
private:
protected:
wxMenuBar* mbar;
wxMenu* mainMenu;
wxStatusBar* statusBar;
// Virtual event handlers, overide them in your derived class
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
virtual void m_menuItemPanelMainOnMenuSelection( wxCommandEvent& event ) { event.Skip(); }
virtual void OnQuit( wxCommandEvent& event ) { event.Skip(); }
public:
GUIFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Test application"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,500 ), long style = wxDEFAULT_FRAME_STYLE );
~GUIFrame();
};
///////////////////////////////////////////////////////////////////////////////
/// Class PanelMAIN
///////////////////////////////////////////////////////////////////////////////
class PanelMAIN : public wxPanel
{
private:
protected:
wxStaticText* m_staticText3;
// Virtual event handlers, overide them in your derived class
virtual void m_btn_Counter_OnButtonClick( wxCommandEvent& event ) { event.Skip(); }
public:
wxStaticText* m_staticTextPMain;
wxButton* m_buttonPMain;
PanelMAIN( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxPoint( 3,3 ), const wxSize& size = wxSize( 350,300 ), long style = wxBORDER_RAISED, const wxString& name = wxEmptyString );
~PanelMAIN();
};
==== GUIFrame.cpp
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif //__BORLANDC__
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif //WX_PRECOMP
#include "GUIFrame.h"
///////////////////////////////////////////////////////////////////////////
GUIFrame::GUIFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
mbar = new wxMenuBar( 0 );
mainMenu = new wxMenu();
wxMenuItem* m_menuItemPanelMain;
m_menuItemPanelMain = new wxMenuItem( mainMenu, wxID_ANY, wxString( wxT("To Main Panel") ) , wxEmptyString, wxITEM_NORMAL );
mainMenu->Append( m_menuItemPanelMain );
wxMenuItem* menuFileQuit;
menuFileQuit = new wxMenuItem( mainMenu, idMenuQuit, wxString( wxT("&Quit") ) + wxT('\t') + wxT("Alt+F4"), wxT("Quit the application"), wxITEM_NORMAL );
mainMenu->Append( menuFileQuit );
mbar->Append( mainMenu, wxT("&Menu") );
this->SetMenuBar( mbar );
statusBar = this->CreateStatusBar( 2, wxSTB_SIZEGRIP, wxID_ANY );
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GUIFrame::OnClose ) );
mainMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( GUIFrame::m_menuItemPanelMainOnMenuSelection ), this, m_menuItemPanelMain->GetId());
mainMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( GUIFrame::OnQuit ), this, menuFileQuit->GetId());
}
GUIFrame::~GUIFrame()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GUIFrame::OnClose ) );
}
PanelMAIN::PanelMAIN( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_APPWORKSPACE ) );
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_staticTextPMain = new wxStaticText( this, wxID_ANY, wxT("We are on PanelMAIN now"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextPMain->Wrap( -1 );
bSizer1->Add( m_staticTextPMain, 0, wxALL, 5 );
m_buttonPMain = new wxButton( this, wxID_ANY, wxT("Counter++"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer1->Add( m_buttonPMain, 0, wxALL, 5 );
m_staticText3 = new wxStaticText( this, wxID_ANY, wxT("0"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText3->Wrap( -1 );
bSizer1->Add( m_staticText3, 0, wxALL, 5 );
this->SetSizer( bSizer1 );
this->Layout();
// Connect Events
m_buttonPMain->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PanelMAIN::m_btn_Counter_OnButtonClick ), NULL, this );
}
PanelMAIN::~PanelMAIN()
{
// Disconnect Events
m_buttonPMain->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PanelMAIN::m_btn_Counter_OnButtonClick ), NULL, this );
}
==== wxPanelAPP.h
#ifndef WXPANELAPP_H
#define WXPANELAPP_H
#include <wx/app.h>
class wxPanelApp : public wxApp
{
public:
virtual bool OnInit();
};
#endif // WXPANELAPP_H
==== wxPanelAPP.cpp
#ifdef WX_PRECOMP
#include "wx_pch.h"
#endif
#ifdef __BORLANDC__
#pragma hdrstop
#endif //__BORLANDC__
#include "wxPanelApp.h"
#include "wxPanelMain.h"
IMPLEMENT_APP(wxPanelApp);
bool wxPanelApp::OnInit()
{
wxPanelFrame* frame = new wxPanelFrame(0L);
frame->SetIcon(wxICON(aaaa)); // To Set App Icon
frame->Show();
return true;
}
==== wxPanelMain.h
#ifndef WXPANELMAIN_H
#define WXPANELMAIN_H
#include "wxPanelApp.h"
#include "GUIFrame.h"
#include "MyPanel.h"
#include <iostream>
class wxPanelFrame: public GUIFrame
{
public:
wxPanelFrame(wxFrame *frame);
~wxPanelFrame();
wxPanel *m_wxpMain = new PanelMAIN(this, wxID_ANY);
private:
virtual void OnClose(wxCloseEvent& event);
virtual void OnQuit(wxCommandEvent& event);
void m_menuItemPanelMainOnMenuSelection( wxCommandEvent& event );
};
#endif // WXPANELMAIN_H
==== wxPanelMain.cpp
#ifdef WX_PRECOMP
#include "wx_pch.h"
#endif
#ifdef __BORLANDC__
#pragma hdrstop
#endif //__BORLANDC__
#include "wxPanelMain.h"
wxPanelFrame::wxPanelFrame(wxFrame *frame) : GUIFrame(frame)
{
#if wxUSE_STATUSBAR
statusBar->SetStatusText(_("Simple Panel Test"), 0);
#endif
// Hide the panel
m_wxpMain->Show(false);
}
wxPanelFrame::~wxPanelFrame()
{
}
void wxPanelFrame::OnClose(wxCloseEvent &event)
{
Destroy();
}
void wxPanelFrame::OnQuit(wxCommandEvent &event)
{
Destroy();
}
void wxPanelFrame::m_menuItemPanelMainOnMenuSelection( wxCommandEvent& event )
{
// Show the panel
m_wxpMain->Show(true);
}
==== MyPanel.h
#ifndef MYPANEL_H
#define MYPANEL_H
#include "GUIFrame.h"
#include <iostream>
class MyPanel : public PanelMAIN
{
public:
MyPanel(wxPanel *panel);
virtual ~MyPanel();
int i{0};
protected:
private:
void m_btn_Counter_OnButtonClick( wxCommandEvent& event );
};
#endif // MYPANEL_H
==== MyPanel.cpp
#include "MyPanel.h"
MyPanel::MyPanel(wxPanel *panel) : PanelMAIN(panel)
{
std::cout << "MyPanel::MyPanel /*CONSTRUCTOR*/\n";
}
MyPanel::~MyPanel()
{
std::cout << "MyPanel::~MyPanel /*DESTRUCTOR*/\n";
}
void MyPanel::m_btn_Counter_OnButtonClick( wxCommandEvent& event )
{
wxString wxs_Count{};
i++;
wxs_Count << i;
m_staticText3->SetLabelText(wxs_Count);
}
You define your event handler in your derived class MyPanel, but you never create and instance of it. The line
wxPanel *m_wxpMain = new PanelMAIN(this, wxID_ANY);
only creates on object of the base class.
You should change this to
MyPanel *m_wxpMain = new MyPanel(this);
You also have an problem with the constructor for MyPanel. The parent needs to be a wxWindow
not wxPanel
. So the declaration should be something like
MyPanel(wxWindow *panel);
and the body should look something like
MyPanel::MyPanel(wxWindow *panel) : PanelMAIN(panel)
{
std::cout << "MyPanel::MyPanel /*CONSTRUCTOR*/\n";
}