Search code examples
c++wxwidgetssizerwxnotebook

sizers and controls next to notebooks


I am facing layout problems implementing controls next to a notebook.

The Problem is, the notebook and the controls next to it are properly aligned as intended, but the ones on th window in the notebook are placed on top of each other, as if there was no sizer used.

I appreciate any kind of input how to fix this.

edit: provided example code to demonstrate the problem

Header test.h:

class mainwindow : public wxFrame{
  public:
    mainwindow(const wxString &title);
     wxWindow *notebookwindow[2];
     wxTextCtrl *onnotebook[2];
     wxNotebook *notebook;
     wxTextCtrl *onmain[2];

     wxBoxSizer *box[4];
};

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

test.cpp

// program test
#include <iostream>
#include <stdlib.h>
#include <string>
#include <map>
#include <typeinfo>
#include <fstream>
#include <vector>
#include <wx/wx.h>
#include <wx/textctrl.h>
#include <wx/notebook.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include "test.h"

mainwindow :: mainwindow (const wxString & title) 
  : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(1000, 800)){
      notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 200));
      notebookwindow[0] = new wxWindow(notebook, wxID_ANY);
      notebookwindow[1] = new wxWindow(notebook, wxID_ANY);

      notebook->AddPage(notebookwindow[0], wxT("This"));
      notebook->AddPage(notebookwindow[1], wxT("That"));

      onmain[0] = new wxTextCtrl(this, wxID_ANY, wxT("on main 1"));
      onmain[1] = new wxTextCtrl(this, wxID_ANY, wxT("on main 2"));

      onnotebook[0] = new wxTextCtrl(notebookwindow[0], wxID_ANY, wxT("on notebook 1"));
      onnotebook[1] = new wxTextCtrl(notebookwindow[0], wxID_ANY, wxT("on notebook 2"));

      box[0] = new wxBoxSizer(wxVERTICAL);
      box[1] = new wxBoxSizer(wxVERTICAL);
      box[2] = new wxBoxSizer(wxHORIZONTAL);

      box[0]->Add(onmain[0]);
      box[0]->Add(onmain[1]);

      box[1]->Add(onnotebook[0]);
      box[1]->Add(onnotebook[1]);

      box[2]->Add(box[0]);
      box[2]->Add(notebook);

      notebookwindow[0]->SetSizer(box[1]);
      this->SetSizer(box[2]);

  }

bool myapp::OnInit(){
  mainwindow *mainfr = new mainwindow(  wxT("test"));
  mainfr->Show(true);

  return true;
}

IMPLEMENT_APP(myapp);

and the makefile

main=test.o 
flags=-std=c++11 -g 
folders=tables sources
gui=`wx-config --cxxflags --libs`


all: $(addprefix doto/,$(main)) 
    $(CXX) $(flags) $^ $(gui) -o test.exe 

doto/%.o:%.cpp %.h
    $(CXX) $(flags) $< $(gui) -c -o doto/$(notdir $(<:.cpp=.o))

.PHONY:clean
clean:
    rm doto/*.o *.exe 

Solution

  • It looks like wxNotebook likes its pages to be fully assembled when they're added. So, moving

    notebook->AddPage(notebookwindow[0], wxT("This"));
    notebook->AddPage(notebookwindow[1], wxT("That"));
    

    right before

    this->SetSizer(box[2]);
    

    fixes the problem.


    Another fix is to force a layout on the notebook page itself after it's fully set up, that is, without changing anything else in the original code, add

    notebookwindow[0]->Layout();
    

    right before

    this->SetSizer(box[2]);
    

    I'm not sure if this behaviour should be considered a bug. I would expect a call to Layout() on the top-level parent to propagate everywhere and avoid such issues, but it looks like it doesn't work like that in this case.

    I don't have time to investigate any further right now; it would be great if we could get VZ.'s opinion on this.