Search code examples
wxwidgets

wxWidgets Sizer does not automatically layout


Here is my code:

cLicensePanel::cLicensePanel( wxWindow * parent )
        : wxPanel(parent,-1,wxPoint(0,0),wxSize(500,500))
    {
        wxBoxSizer * szrUserKey = new wxBoxSizer(wxHORIZONTAL);
        myUserKeyCtrl = new wxTextCtrl(this,-1,L"");
        szrUserKey->Add( new wxStaticText(this,-1,wxString(L"User's ComputerKey:")),
                   0,wxALL,10);
        szrUserKey->Add( myUserKeyCtrl,0,wxALL,10);
        szrUserKey->Add( new wxButton(this,IDC_Generate,L"Generate"),0,wxALL,10);
        SetSizer( szrUserKey );
    }

This is intended to produce this display, with the 3 widgets neatly arranged in a row.

enter image description here

However, what I actually get is all the widgets piled one on top of the other

enter image description here

Why?

I can force the correct display by adding an explicit call to Sizer::Layout()

cLicensePanel::cLicensePanel( wxWindow * parent )
        : wxPanel(parent,-1,wxPoint(0,0),wxSize(500,500))
    {
        wxBoxSizer * szrUserKey = new wxBoxSizer(wxHORIZONTAL);
        myUserKeyCtrl = new wxTextCtrl(this,-1,L"");
        szrUserKey->Add( new wxStaticText(this,-1,wxString(L"User's Computer Key:")),0,wxALL,10);
        szrUserKey->Add( myUserKeyCtrl,0,wxALL,10);
        szrUserKey->Add( new wxButton(this,IDC_Generate,L"Generate"),0,wxALL,10);
        szrUserKey->Layout();
        SetSizer( szrUserKey );
    }

I can live with this, though it seems to me that it should be unnecessary to call Layout. I also suspect that the reason the Layout call is neccessary might be an important clue to the problem that has me stumped.

The above is the behaviour when using wxWidgets v2.8.12. I am upgrading to v2.9.3.

In the new version the initial code, without the call to Layout(), shows the same problem with the widgets all piled on top of each other. If I add the call to layout() in v2.9.3 then I cannot see any of the widgets at all - the panel shows completely blank!


Solution

  • SetSizer() intentionally doesn't do the layout, it only happens when the window is resized. But it also so happens that a newly created window always gets a EVT_SIZE, soon after being shown, so by the time the user sees it, it's already laid out (and this is the reason SetSizer() doesn't do it: this would be wasteful as it would be redone very soon anyhow in 99% of cases).

    In your case the panel doesn't get this size event for whatever reason. Perhaps -- looking at the rest of your code -- you can see what it is and avoid it. But if not, calling Layout() is a fine solution too. Except that you should call the same method on the panel itself, not on the sizer, i.e. do

    cLicensePanel::cLicensePanel( wxWindow * parent )
    {
        ...
        SetSizer(szrUserKey);
        Layout();
    }