Search code examples
c++wxwidgets

Panel class module initialization in C++ GUIapp


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

Solution

  • 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";
    }