首页 > 解决方案 > C++ GUIapp中的面板类模块初始化

问题描述

我是 C++ 和 wxWidgets 的新手,使用 wxFormBuilder 帮助我创建 GUI。

我喜欢将类似的功能放在一个模块中的想法,这意味着我的应用程序有多个模块。其中一个模块用于 GUI(它现在包含主框架(只有一个菜单和任务栏)和一个面板(带有 2 个静态文本控件和一个按钮)的代码。按钮增加一个计数器,值显示在一个面板上的静态文本。

到目前为止,一切都很好。(编译没有错误)我可以使面板显示/隐藏,但我似乎错过了使面板按钮工作的基本知识。我尝试的方式都类似于 Main 模块的编码方式,但这不起作用。

我了解它如何与同一文件中的 GUI 类元素一起使用。但是,我喜欢将所有 GUI 代码保存在一个模块 (GUIFrame.h/.cpp) 中,并将所有“功能”代码保存在例如 Panel 模块 (MyPanel.h/.cpp) 中。

只是因为我不确定我在哪里犯了错误,所以我在这篇文章中展示了所有代码。我很抱歉,如果它太多了。

希望有人可以帮助我弥合我对这种工作方式的知识差距。

问候, 路德

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

标签: c++wxwidgets

解决方案


您在派生类 MyPanel 中定义事件处理程序,但您从不创建它并实例化它。线

wxPanel *m_wxpMain = new PanelMAIN(this, wxID_ANY);

仅在基类的对象上创建。

您应该将其更改为

MyPanel *m_wxpMain = new MyPanel(this);

MyPanel 的构造函数也有问题。父母必须是wxWindownot wxPanel。所以声明应该是这样的

MyPanel(wxWindow *panel);

身体应该看起来像

MyPanel::MyPanel(wxWindow *panel) : PanelMAIN(panel)
{
    std::cout << "MyPanel::MyPanel /*CONSTRUCTOR*/\n";
}

推荐阅读