Question

I have a trouble with adding 4 or more wxBoxSizer (or any other type of Sizer objects) in C++ GUI application. This is my first time creating a GUI application using wxWidgets and I am using Code::Blocks as the IDE. Please help me If anybody had this problem before and resolved it.

Below is the complete program.

Main frame class implementaions:

/***************************************************************
 * Name:      testWXWProjectMain.h
 * Purpose:   Defines Application Frame
 * Author:    test ()
 * Created:   2014-01-22
 * Copyright: test ()
 * License:
 **************************************************************/

#ifndef TESTWXWPROJECTMAIN_H
#define TESTWXWPROJECTMAIN_H

//(*Headers(testWXWProjectFrame)
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/menu.h>
#include <wx/panel.h>
#include <wx/statusbr.h>
#include <wx/frame.h>
//*)

class testWXWProjectFrame: public wxFrame
{
    public:

        testWXWProjectFrame(wxWindow* parent,wxWindowID id = -1);
        virtual ~testWXWProjectFrame();

    private:

        //(*Handlers(testWXWProjectFrame)
        void OnQuit(wxCommandEvent& event);
        void OnAbout(wxCommandEvent& event);
        //*)

        //(*Identifiers(testWXWProjectFrame)
        static const long ID_BUTTON1;
        static const long ID_BUTTON2;
        static const long ID_PANEL2;
        static const long ID_PANEL1;
        static const long ID_MENUITEM1;
        static const long idMenuAbout;
        static const long ID_STATUSBAR1;
        //*)

        //(*Declarations(testWXWProjectFrame)
        wxPanel* Panel1;
        wxStatusBar* StatusBar1;
        wxButton* Button1;
        wxButton* Button2;
        wxPanel* Panel2;
        //*)

        DECLARE_EVENT_TABLE()
};

#endif // TESTWXWPROJECTMAIN_H


####################################################
/***************************************************************
 * Name:      testWXWProjectMain.cpp
 * Purpose:   Code for Application Frame
 * Author:    test ()
 * Created:   2014-01-22
 * Copyright: test ()
 * License:
 **************************************************************/

#include "testWXWProjectMain.h"
#include <wx/msgdlg.h>

//(*InternalHeaders(testWXWProjectFrame)
#include <wx/string.h>
#include <wx/intl.h>
//*)

//helper functions
enum wxbuildinfoformat {
    short_f, long_f };

wxString wxbuildinfo(wxbuildinfoformat format)
{
    wxString wxbuild(wxVERSION_STRING);

    if (format == long_f )
    {
#if defined(__WXMSW__)
        wxbuild << _T("-Windows");
#elif defined(__UNIX__)
        wxbuild << _T("-Linux");
#endif

#if wxUSE_UNICODE
        wxbuild << _T("-Unicode build");
#else
        wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
    }

    return wxbuild;
}

//(*IdInit(testWXWProjectFrame)
const long testWXWProjectFrame::ID_BUTTON1 = wxNewId();
const long testWXWProjectFrame::ID_BUTTON2 = wxNewId();
const long testWXWProjectFrame::ID_PANEL2 = wxNewId();
const long testWXWProjectFrame::ID_PANEL1 = wxNewId();
const long testWXWProjectFrame::ID_MENUITEM1 = wxNewId();
const long testWXWProjectFrame::idMenuAbout = wxNewId();
const long testWXWProjectFrame::ID_STATUSBAR1 = wxNewId();
//*)

BEGIN_EVENT_TABLE(testWXWProjectFrame,wxFrame)
    //(*EventTable(testWXWProjectFrame)
    //*)
END_EVENT_TABLE()

testWXWProjectFrame::testWXWProjectFrame(wxWindow* parent,wxWindowID id)
{
    //(*Initialize(testWXWProjectFrame)
    wxMenuItem* MenuItem2;
    wxMenuItem* MenuItem1;
    wxBoxSizer* BoxSizer3;
    wxMenu* Menu1;
    wxBoxSizer* BoxSizer2;
    wxBoxSizer* BoxSizer4;
    wxBoxSizer* BoxSizer1;
    wxMenuBar* MenuBar1;
    wxMenu* Menu2;

    Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY"));
    BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
    BoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
    Panel2 = new wxPanel(this, ID_PANEL2, wxDefaultPosition, wxSize(236,171), wxTAB_TRAVERSAL, _T("ID_PANEL2"));
    BoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
    Button1 = new wxButton(Panel2, ID_BUTTON1, _("button 1"), wxDefaultPosition, wxSize(121,27), 0, wxDefaultValidator, _T("ID_BUTTON1"));
    BoxSizer4->Add(Button1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button2 = new wxButton(Panel2, ID_BUTTON2, _("button2"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON2"));
    BoxSizer4->Add(Button2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Panel2->SetSizer(BoxSizer4);
    SetSizer(BoxSizer4);
    Layout();
    BoxSizer2->Add(Panel2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer1->Add(BoxSizer2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
    Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxSize(262,206), wxTAB_TRAVERSAL, _T("ID_PANEL1"));
    BoxSizer3->Add(Panel1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer1->Add(BoxSizer3, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    SetSizer(BoxSizer1);
    MenuBar1 = new wxMenuBar();
    Menu1 = new wxMenu();
    MenuItem1 = new wxMenuItem(Menu1, ID_MENUITEM1, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
    Menu1->Append(MenuItem1);
    MenuBar1->Append(Menu1, _("&File"));
    Menu2 = new wxMenu();
    MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
    Menu2->Append(MenuItem2);
    MenuBar1->Append(Menu2, _("Help"));
    SetMenuBar(MenuBar1);
    StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
    int __wxStatusBarWidths_1[1] = { -1 };
    int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
    StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
    StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
    SetStatusBar(StatusBar1);
    BoxSizer1->Fit(this);
    BoxSizer1->SetSizeHints(this);

    Connect(ID_MENUITEM1,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testWXWProjectFrame::OnQuit);
    Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&testWXWProjectFrame::OnAbout);
    //*)
}

testWXWProjectFrame::~testWXWProjectFrame()
{
    //(*Destroy(testWXWProjectFrame)
    //*)
}

void testWXWProjectFrame::OnQuit(wxCommandEvent& event)
{
    Close();
}

void testWXWProjectFrame::OnAbout(wxCommandEvent& event)
{
    wxString msg = wxbuildinfo(long_f);
    wxMessageBox(msg, _("Welcome to..."));
}

Application class:

/***************************************************************
 * Name:      testWXWProjectApp.h
 * Purpose:   Defines Application Class
 * Author:    test ()
 * Created:   2014-01-22
 * Copyright: test ()
 * License:
 **************************************************************/

#ifndef TESTWXWPROJECTAPP_H
#define TESTWXWPROJECTAPP_H

#include <wx/app.h>

class testWXWProjectApp : public wxApp
{
    public:
        virtual bool OnInit();
};

#endif // TESTWXWPROJECTAPP_H

    /***************************************************************
 * Name:      testWXWProjectApp.cpp
 * Purpose:   Code for Application Class
 * Author:    test ()
 * Created:   2014-01-22
 * Copyright: test ()
 * License:
 **************************************************************/

#include "testWXWProjectApp.h"

//(*AppHeaders
#include "testWXWProjectMain.h"
#include <wx/image.h>
//*)

IMPLEMENT_APP(testWXWProjectApp);

bool testWXWProjectApp::OnInit()
{
    //(*AppInitialize
    bool wxsOK = true;
    wxInitAllImageHandlers();
    if ( wxsOK )
    {
        testWXWProjectFrame* Frame = new testWXWProjectFrame(0);
        Frame->Show();
        SetTopWindow(Frame);
    }
    //*)
    return wxsOK;

}

Debug:

Adding source dir: /home/nisshanka/projects/codes/testWXWProject/
Adding source dir: /home/nisshanka/projects/codes/testWXWProject/
Adding file: /home/nisshanka/projects/codes/testWXWProject/bin/Debug/testWXWProject
Changing directory to: /home/nisshanka/projects/codes/testWXWProject/.
Set variable: LD_LIBRARY_PATH=.:/usr/local/lib:/usr/lib64:
Starting debugger: /usr/bin/gdb -nx -fullname  -quiet  -args /home/nisshanka/projects/codes/testWXWProject/bin/Debug/testWXWProject
done
Registered new type: wxString
Registered new type: STL String
Registered new type: STL Vector
Setting breakpoints
Debugger name and version: GNU gdb (GDB) Red Hat Enterprise Linux (7.2-56.el6)
At /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:26
At /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27
Continuing...
Program received signal SIGSEGV, Segmentation fault.
In wxSizer::GetMinSize() () (/usr/local/lib/libwx_gtk2_core-2.8.so.0)
#20 0x0000000000409d06 in testWXWProjectApp::OnInit (this=0x630840) at /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27
/home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27:626:beg:0x409d06
At /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27
#20 0x0000000000409d06 in testWXWProjectApp::OnInit (this=0x630840) at /home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27
/home/nisshanka/projects/codes/testWXWProject/testWXWProjectApp.cpp:27:626:beg:0x409d06
Continuing...
Program terminated with signal SIGSEGV, Segmentation fault.
Debugger finished with status 0

I tried with different sizers too but always giving the segmentation fault. if I use 3 sizers then it doesn't have any problem. Thanks.

Was it helpful?

Solution

You can't set a sizer to multiple wxWindows. For example, in testWXWProjectFrame::testWXWProjectFrame, you have

Panel2->SetSizer(BoxSizer4);
SetSizer(BoxSizer4);

This will set the same sizer to Panel2, which is created as a child of the frame, and to the frame itself. Generally, you need to create one box sizer for each container (wxPanel, wxFrame) and associate that sizer with the container using wxWindow::SetSizer. Additionally, if a sizer is created for a particular container, e.g. Panel2, then only the children of Panel2 may be added to that sizer (or a sizer that itself only contains children of Panel2.

In your code, these relations are all mixed up. Also, why do you first set BoxSizer4 as the frame's sizer and then, at the end of the method, replace it with BoxSizer1?

I also suggest that you use meaningful names for your variables. It's quite hard to read the source code if it contains names like BoxSizer1 and Panel2. Additionally, I have sometimes found it helpful to write the control / sizer hierarchy as a tree like this:

  • Frame (BoxSizer4)
    • Panel2 (BoxSizer4)
      • Button1
      • Button2
    • Panel1 (BoxSizer3)

This makes it easier to check that you add the right controls to the right sizers, and set the sizers to the containers correctly. Here, you can quickly spot that BoxSizer4 is set to two controls where one is a child of the other - this will cause a crash such as the one you are seeing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top