wxBoxSizer Layout Problem (xwNewbie...) Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
smf
Knows some wx things
Knows some wx things
Posts: 32
Joined: Wed Nov 12, 2008 7:04 pm

wxBoxSizer Layout Problem (xwNewbie...)

Post by smf » Thu Nov 13, 2008 7:54 pm

Hi,

as I can not find a solution for this by myself, I dare to ask what I am doing wrong here...

The first image shows, what I get with my code and the second image shows how it should look like (or what I expected to get)... Problem is whatever the last element in my wxBoxSizers is, it is vertikaly cropped by the height of approximatly one Butten-Height.?!

Could anyone please give me a hint, what stupid things I am doing there (I think the Problem sits in front of the screen, because this is my first attempt in setting up a GUI with wx...)

many thanks!
Stefan

Code: Select all

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, -1, title, pos, size) , m_timer(this, TIMER_ID)
{
    // Top-level-sizer in frame
    wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
    
    // first sizer
    wxBoxSizer* mySizer0 = new wxBoxSizer( wxVERTICAL );
    
    // second sizer
    wxBoxSizer* mySizer1 = new wxBoxSizer( wxHORIZONTAL );
    
    // third sizer
    wxBoxSizer* mySizer2 = new wxBoxSizer( wxVERTICAL );
    
    // create some buttons/radiobuttons in sizer 2
    mySizer2->Add( 
        new wxButton(this, wxID_OK, wxT("Button1")),
        0,        // make vertically stretchable
        wxEXPAND| // make horizontally stretchable
        wxALL,    // and make border all around
        4  );     // set border width to 10
        
    mySizer2->Add( 
        new wxButton(this, wxID_OK, wxT("Button2")),
        0,        // make vertically stretchable
        wxEXPAND| // make horizontally stretchable
        wxALL,    // and make border all around
        4  );     // set border width to 10
        
    mySizer2->Add( 
        new wxButton(this, wxID_OK, wxT("Button3")),
        0,        // make vertically stretchable
        wxEXPAND| // make horizontally stretchable
        wxALL,    // and make border all around
        4  );     // set border width to 10
        
    // Add Sizer 2 to Sizer 1
    mySizer1->Add(
        mySizer2,
        0,        // make vertically stretchable
        wxEXPAND| // make horizontally stretchable
        wxALL,    // and make border all around
        4 );     // set border width to 10
    
    // Add a Spacer to Sizer 1
    mySizer1->AddSpacer( 256 );
    
    // Add Sizer 1 to Sizer 0
    mySizer0->Add(
        mySizer1,
        0,        // make vertically stretchable
        wxEXPAND| // make horizontally stretchable
        wxALL,    // and make border all around
        4 );     // set border width to 10
    
    // Create text-control inside sizer0
    // wxFont* myFont = new wxFont(10,wxFONTFAMILY_TELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false);
    mySizer0->Add( 
        new wxTextCtrl(this, wxID_ANY, wxT("\n"),wxDefaultPosition,wxDefaultSize,wxTE_MULTILINE|wxTE_READONLY),
        0,        // make vertically stretchable
        wxEXPAND| // make horizontally stretchable
        wxALL,    // and make border all around
        4 );     // set border width to 10
    
    // Add Sizer 0 to toplevelSizer...
    topSizer->Add(
        mySizer0,
        0,        // make vertically stretchable
        wxEXPAND| // make horizontally stretchable
        wxALL,    // and make border all around
        4 );     // set border width to 10
    
    // use sizer for layout
    topSizer->Fit( this );          // fit the dialog to the contents
    topSizer->SetSizeHints( this ); // set hints to honor min size
    topSizer->Layout();
    SetSizer( topSizer );
    
    std::cerr << "topSizer->GetChildren().size()=" << topSizer->GetChildren().size();

Attachments
expected.jpg
This is what I would expect it to look like...
expected.jpg (7.13 KiB) Viewed 1590 times
whatiget.jpg
This is what I get...
whatiget.jpg (7.26 KiB) Viewed 1590 times

DavidHart
Site Admin
Site Admin
Posts: 3906
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Post by DavidHart » Thu Nov 13, 2008 11:01 pm

Hi,
4 ); // set border width to 10
Almost. ;)
0, // make vertically stretchable
Unless you believe that your compiler reads comments, this doesn't do what you think.

A proportion of 0 means that the item doesn't stretch in the direction of the sizer (e.g. vertically in a wxVERTICAL boxsizer). A proportion of >0 means it will stretch. So change your mySizer0->Add( new wxTextCtrl(... line to use 1 instead of 0, and it should grow vertically (perhaps by more than you want...).

BTW, this sort of thing is so much easier to sort out in a form designer, as you can play with the various attributes and immediately see what will happen.

Regards,

David

smf
Knows some wx things
Knows some wx things
Posts: 32
Joined: Wed Nov 12, 2008 7:04 pm

Post by smf » Thu Nov 13, 2008 11:55 pm

Hi David,
DavidHart wrote:
4 ); // set border width to 10
Almost. ;)
I am sorry for the wrong remarks.

These were leftovers when experimenting with the various settings there... As I am new to wx, I changed the setting without changing the comment...

But: The behavior of the missing portion of part of the wxframe is just the same with or without the border set to 10 or to 4. And it is just the same if I try to allow resizing for a) all b) just one c) no element in the sizers...

So, yes, you are right, the comments didn't make any sense but they are not the reason for that strange behavior. The reason why I changed them was my hope to find out, if changing them would alter anything with that layout-problem... sadly it doesn't...


all the best,
Stefan

timg
Earned some good credits
Earned some good credits
Posts: 148
Joined: Mon Jan 23, 2006 6:52 pm

Post by timg » Fri Nov 14, 2008 1:28 am

Did you try making these calls:

Code: Select all

    topSizer->Fit( this );          // fit the dialog to the contents
    topSizer->SetSizeHints( this ); // set hints to honor min size
after this?

Code: Select all

    SetSizer( topSizer );

smf
Knows some wx things
Knows some wx things
Posts: 32
Joined: Wed Nov 12, 2008 7:04 pm

Post by smf » Fri Nov 14, 2008 1:42 am

timg wrote:Did you try making these calls:

Code: Select all

    topSizer->Fit( this );          // fit the dialog to the contents
    topSizer->SetSizeHints( this ); // set hints to honor min size
after this?

Code: Select all

    SetSizer( topSizer );
Yes, I have tried that, too. It makes no difference...

Stefan

timg
Earned some good credits
Earned some good credits
Posts: 148
Joined: Mon Jan 23, 2006 6:52 pm

Post by timg » Fri Nov 14, 2008 8:14 am

Why are you setting the size of your wxTextCtrl to wxDefaultSize ?

smf
Knows some wx things
Knows some wx things
Posts: 32
Joined: Wed Nov 12, 2008 7:04 pm

Post by smf » Fri Nov 14, 2008 9:27 am

timg wrote:Why are you setting the size of your wxTextCtrl to wxDefaultSize ?
this also was a test if anything changes... I have changed that back to 100x100 (and 320x100) and all remains like it is... This must be something other. Even if I completely remove the textCtrl, the vertical height of the sizer is too small.

I tried to just do this in just only one single vertical BoxSizer:

Button1

Button2

Button3

Button4

What I get is three Buttons visable (until i manually change the window-size by resizing it...). So the fourth Button *is* there. It just doesn't get displayed...

all the best,
Stefan

TrV
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 630
Joined: Wed Jul 04, 2007 1:12 pm

Post by TrV » Fri Nov 14, 2008 10:03 am

What shocks me in the total absence of panels... is it me who does not know how to construct GUI right ?

DavidHart
Site Admin
Site Admin
Posts: 3906
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Post by DavidHart » Fri Nov 14, 2008 11:01 am

Hi Stefan,
So, yes, you are right, the comments didn't make any sense but they are not the reason for that strange behavior.
I know, I was joking.
The reason why I changed them was my hope to find out, if changing them would alter anything with that layout-problem... sadly it doesn't...
Did you change the textctrl line to:
mySizer0->Add( new wxTextCtrl(...), 1, wxEXPAND|wxALL,4);
What I get is three Buttons visable (until i manually change the window-size by resizing it...). So the fourth Button *is* there. It just doesn't get displayed...
That is improves with resizing usually means that you need a call to topSizer->Layout();. You already have this in your posted code, but perhaps it should go after you SetSizer.

Having said all that, I'm not sure I understand what you want. The images in your original post showed 3 buttons, with a textctrl that was too small in the 'wrong' picture. I can only see 3 buttons in the code too. This makes the appearance of a fourth button a bug (yes, I'm joking again ;) ).
Perhaps you could explain again just what you see as the problem, and post your current code.

@TrV:
Yes, you are right to say that it would be better to have a wxPanel as the sole child of the frame, with everything else happening inside that panel. But I doubt if it's the problem here.

smf
Knows some wx things
Knows some wx things
Posts: 32
Joined: Wed Nov 12, 2008 7:04 pm

Post by smf » Fri Nov 14, 2008 11:41 am

Hi David,
DavidHart wrote: I know, I was joking.
I was hoping so... But as I have the general experience with forums in that there are some, erm say, "unpolite" people arround, sometimes -- esp. if it is silly newbies (aka idiots... :D) questions... so I wasn't completely sure about that...
That is improves with resizing usually means that you need a call to topSizer->Layout();. You already have this in your posted code, but perhaps it should go after you SetSizer.
Well, it seems like this being the top-hint I needed. (I should have posted the full constructor, I fear... because there is a menu below topSizer->Layout();.) After deactivating that menu, the layout is as expected. So I guess, that the sizer's calculations get screewd up because of my menu-code below that line... (Seems like the height of the menu is approx. the height of a button...).
Having said all that, I'm not sure I understand what you want.
Neither is me... :D ... SCNR...
The images in your original post showed 3 buttons, with a textctrl that was too small in the 'wrong' picture. I can only see 3 buttons in the code too. This makes the appearance of a fourth button a bug (yes, I'm joking again ;) ).
Well despite of the missing fourth button in that code-snipplet :D the textCtrl(...); was not vertically too small. It was "clipped" (or cut) by the wxFrame-Border. If it had been just to small, I most probably wouldn't have noticed it ... *g*
Perhaps you could explain again just what you see as the problem, and post your current code.
I currently think, that your hint with the position of topSizer->Layout(); in the source being the main reason. Seems like I asked for trouble and got it...

I will change that (with the menu active...) and see what happens, first. But currently I fear that this could be exactly the problem.
@TrV:
Yes, you are right to say that it would be better to have a wxPanel as the sole child of the frame, with everything else happening inside that panel. But I doubt if it's the problem here.
Ok, my current structure of myFrame (wxFrame) is:

wxFrame -> topSizer -> someOtherSizers -> Menu.

If I get that above right, it would be better to have something like this:

wxFrame -> wxPanel -> topSizer -> someOtherSizers -> Menu

or, if the menu-position in the source being the cause of the trouble something like this:

wxFrame -> Menu -> wxPanel -> topSizer -> someOtherSizers

OK, now I will be experimenting with that again... I really want to know now, what weird things I was doing there. :D

all the best and many, many thanks, so far,
Stefan

smf
Knows some wx things
Knows some wx things
Posts: 32
Joined: Wed Nov 12, 2008 7:04 pm

Oscilloscope in wxFrame?

Post by smf » Fri Nov 14, 2008 5:04 pm

Hi,

for all of the people who probably stumble across the same problem... :D the ->Layout() must just be at the very end and everything is fine...

To just ask another question: I can blit an image to the frame with dc.drawImage() and it works all like I would expect it... but is that the recommended way of creating eg. an oscilloscope? (The program should become a RTTY/CW-Decoder for HAM-radio and so it needs some "real-time"-tuning-aid. Best way for RTTY would be an X/Y-Oscilloscope-View of some internal signals inside the decoder...)

all the best,
Stefan

TrV
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 630
Joined: Wed Jul 04, 2007 1:12 pm

Post by TrV » Sat Nov 15, 2008 5:25 pm

I'm not sure using panels won't solve your problems.

With no panels, you've got only sizers, and different strategies of differents sizers in one and only panel may be the responsible for graphic objects which overlap.

Using panels with only one strategy (/sizer) for each one cannot by definition cause graphic objects to overlap.

Maybe haven't i analyze the problem enough...

Post Reply