1

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.

Nishantha
  • 21
  • 4
  • Compile in debug mode and then run your program with a debugger. Step through your code until it crashes. Which line is that? – Jonas Bötel Feb 10 '14 at 05:42
  • Hi LumpN, I debugged through the code. compiler can load all objects but segmentation fault is occurred once it calls Frame->Show(); method in testWXWProjectApp.cpp file.Is this because of memory leaks ? – Nishantha Feb 10 '14 at 06:21
  • `At .../testWXWProject/testWXWProjectApp.cpp:27 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 /../../testWXWProjectApp.cpp:27 #20 0x0000000000409d06 in testWXWProjectApp::OnInit (this=0x630840) at .../testWXWProjectApp.cpp:27 /../testWXWProjectApp.cpp:27:626:beg:0x409d06` – Nishantha Feb 10 '14 at 06:47

1 Answers1

2

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.

Kristian Duske
  • 1,769
  • 9
  • 14
  • Yes you are correct. I checked again and modified, now it is working. This actually happen when adding the items using Code::Blocks wxSmith plugging. As a summary I have to be careful to use SetSizer() for each Sizers only one time, Thanks for the help. – Nishantha Feb 10 '14 at 11:11
  • I noticed that wxSmith automatically creates faulty code exactly like that shown above if any panels, frames etc do not have "Default Size" checked. It is easy to do because default size is switched off if you ever drag the edges of the boxes while creating the interface. To fix - simply check "Default Size" on everything and re-build. – kshepherd May 30 '16 at 15:45