Page 1 of 2

wxGrid + wxButton in wxFlexGridSizer

Posted: Tue Sep 15, 2009 9:42 am
by Dobias
Hello dear Community,

i have a problem with my UI design with wxWidgets:
I want to have a table (wxGrid) and four buttons below it on a panel.
If the table becomes too long so that it does not fit into the window any more, i want it to have scrollbars into the necessary direction.
The buttons should be visible in any case.

My actual code in the constructor of my wxPanel-child-class looks like this:

Code: Select all

wxGridSizer* buttonSizer = new wxGridSizer( 1, 4, 10, 10 );
		
buttonSizer->Add( Button1 );
buttonSizer->Add( Button2 );
buttonSizer->Add( Button3 );
buttonSizer->Add( Button4 );

wxFlexGridSizer* tableFlexGridSizer = new wxFlexGridSizer( 2, 1, 10, 10 );
tableFlexGridSizer->AddGrowableRow( 1 );
tableFlexGridSizer->Add( LoadGrid, 1, wxGROW );
tableFlexGridSizer->Add( buttonSizer, 1, wxGROW );

tableFlexGridSizer->Fit( this );
tableFlexGridSizer->SetSizeHints( this );

SetSizer( tableFlexGridSizer );
Unfortunately it looks like this:
picture 1:
Image
The white area right of the table should not be there.

picture 2:
Image
The table should be not that high so that the buttons are visible.

It would be great if you could help me, because i don't get to my goal in spite of having tried much on my own and read some tutorials.

many thanks in advance
Dobias

Posted: Tue Sep 15, 2009 3:51 pm
by Auria
I'd envision something simpler :


Code: Select all

+-----------------------+
|  vertical box sizer   |
|                       |
|         GRID          |
|                       |
|                       |
|+--------------------+ |
|| h box sizer + btns | |
|+--------------------+ |
+-----------------------+

You'd give the grid a proportion of 1 (scale) + wxEXPAND, and the bottom sizr a proportion of 0

This way, even if the window is made smaller, the buttons would still appear at the bottom.

Posted: Wed Sep 16, 2009 6:48 am
by Dobias
Hi Auria,

thank you for the suggestion, but i can't get your version to work either.

Not it looks like this:
Image

My code in the constructor of my wxPanel-child-class now looks like this:

Code: Select all

wxBoxSizer* horizontalBoxSizer = new wxBoxSizer( wxHORIZONTAL );
		
horizontalBoxSizer->Add( Button1 );
horizontalBoxSizer->Add( Button2 );
horizontalBoxSizer->Add( Button3 );
horizontalBoxSizer->Add( Button4 );

wxBoxSizer* verticalBoxSizer = new wxBoxSizer( wxVERTICAL );
verticalBoxSizer->Add( LoadGrid, 1, wxEXPAND );
verticalBoxSizer->Add( horizontalBoxSizer, 0 );

verticalBoxSizer->Fit( this );
verticalBoxSizer->SetSizeHints( this );

SetSizer( verticalBoxSizer );
What am i doing wrong? :-)

Posted: Wed Sep 16, 2009 9:10 am
by catalin

Code: Select all

wxBoxSizer* horizontalBoxSizer = new wxBoxSizer( wxHORIZONTAL );
		
horizontalBoxSizer->Add( Button1, 1 );
horizontalBoxSizer->Add( Button2, 1 );
horizontalBoxSizer->Add( Button3, 1 );
horizontalBoxSizer->Add( Button4, 1 );

wxBoxSizer* verticalBoxSizer = new wxBoxSizer( wxVERTICAL );
verticalBoxSizer->Add( LoadGrid, 1, wxEXPAND );
verticalBoxSizer->Add( horizontalBoxSizer, 0, wxEXPAND );

SetSizer( verticalBoxSizer );
verticalBoxSizer->Layout();
verticalBoxSizer->Fit( this );

//there should be no need for this:
//verticalBoxSizer->SetSizeHints( this ); 
How's that?

Posted: Wed Sep 16, 2009 11:04 am
by Dobias
Thank you. That is better but still not perfect.

The good thing is, that the buttons stay visible now when the grid is forced to have scrollbars.
Image

The drawback is, that the unused space is filled with white color (which i guess comes from the grid.
Image

Do you know how i can get rid of this?

Posted: Wed Sep 16, 2009 11:10 am
by catalin
Dobias wrote:the unused space is filled with white color (which i guess comes from the grid.
Do you know how i can get rid of this?
wxGrid::AutoSizeColumn[s]

Posted: Wed Sep 16, 2009 11:48 am
by Dobias
Ok, now i have

Code: Select all

LoadGrid->AutoSizeColumns();

wxBoxSizer* horizontalBoxSizer = new wxBoxSizer( wxHORIZONTAL );
               
horizontalBoxSizer->Add( Button1, 1 );
horizontalBoxSizer->Add( Button2, 1 );
horizontalBoxSizer->Add( Button3, 1 );
horizontalBoxSizer->Add( Button4, 1 );

wxBoxSizer* verticalBoxSizer = new wxBoxSizer( wxVERTICAL );
verticalBoxSizer->Add( LoadGrid, 1, wxEXPAND );
verticalBoxSizer->Add( horizontalBoxSizer, 0, wxEXPAND );

SetSizer( verticalBoxSizer );
verticalBoxSizer->Layout();
verticalBoxSizer->Fit( this ); 
but the result is still the same.

Posted: Wed Sep 16, 2009 11:56 am
by catalin
Dobias wrote:

Code: Select all

LoadGrid->AutoSizeColumns();
but the result is still the same.
The world would have been way ahead if people had actually read the docs.. :)

Call LoadGrid->AutoSizeColumns( false );

Posted: Wed Sep 16, 2009 12:03 pm
by Dobias
I'm very sorry, but

Code: Select all

LoadGrid->AutoSizeColumns( false );

wxBoxSizer* horizontalBoxSizer = new wxBoxSizer( wxHORIZONTAL );
               
horizontalBoxSizer->Add( Button1, 1 );
horizontalBoxSizer->Add( Button2, 1 );
horizontalBoxSizer->Add( Button3, 1 );
horizontalBoxSizer->Add( Button4, 1 );

wxBoxSizer* verticalBoxSizer = new wxBoxSizer( wxVERTICAL );
verticalBoxSizer->Add( LoadGrid, 1, wxEXPAND );
verticalBoxSizer->Add( horizontalBoxSizer, 0, wxEXPAND );

SetSizer( verticalBoxSizer );
verticalBoxSizer->Layout();
verticalBoxSizer->Fit( this );
produces the same result (much white space).

Posted: Wed Sep 16, 2009 12:23 pm
by catalin
How do you create the Grid?

Posted: Thu Sep 17, 2009 7:54 am
by Dobias
I've reduced the problem to a minimal example to make things easier.

It looks like this:

Code: Select all

#include "wx/wx.h" 
#include "wx/grid.h"

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

class MyFrame: public wxFrame
{
public:
    MyFrame( const wxString& title, const wxPoint& pos, const wxSize& size );
};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
    MyFrame *frame = new MyFrame( "Dobiasds SizerTest", wxPoint( -1, -1 ), wxSize( -1, -1 ) );
    frame->Show( true );
    return TRUE;
} 

MyFrame::MyFrame( const wxString& title, const wxPoint& pos, const wxSize& size )
: wxFrame( (wxFrame*) NULL, -1, title, pos, size )
{
	wxGrid* grid = new wxGrid( this, wxID_ANY );
	grid->CreateGrid( 20, 10 );
	grid->AutoSizeColumns( false );

	wxButton* button1 = new wxButton( this, wxID_ANY, "button1" );
	wxButton* button2 = new wxButton( this, wxID_ANY, "button2" );
	wxButton* button3 = new wxButton( this, wxID_ANY, "button3" );
	wxButton* button4 = new wxButton( this, wxID_ANY, "button4" );

	wxBoxSizer* horizontalBoxSizer = new wxBoxSizer( wxHORIZONTAL );

	horizontalBoxSizer->Add( button1, 1 );
	horizontalBoxSizer->Add( button2, 1 );
	horizontalBoxSizer->Add( button3, 1 );
	horizontalBoxSizer->Add( button4, 1 );

	wxBoxSizer* verticalBoxSizer = new wxBoxSizer( wxVERTICAL );
	verticalBoxSizer->Add( grid, 1, wxEXPAND );

	verticalBoxSizer->Add( horizontalBoxSizer, 0, wxEXPAND );

	SetSizer( verticalBoxSizer );
	verticalBoxSizer->Layout();
	verticalBoxSizer->Fit( this ); 
}
I do have the same problems here.

Posted: Thu Sep 17, 2009 9:26 am
by catalin
hmm.. I checked the wxGrid sources a bit and it seems that it should work if you call grid->AutoSize() (..same as grid->Fit()) at the end of MyFrame constructor, as it will add the remaining space to the last column.
But I did not test anything.

Posted: Thu Sep 17, 2009 11:06 am
by Dobias
Ok, now i have

Code: Select all

#include "wx/wx.h" 
#include "wx/grid.h"

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

class MyFrame: public wxFrame
{
public:
    MyFrame( const wxString& title, const wxPoint& pos, const wxSize& size );
};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
    MyFrame *frame = new MyFrame( "Dobiasds SizerTest", wxPoint( -1, -1 ), wxSize( -1, -1 ) );
    frame->Show( true );
    return TRUE;
} 

MyFrame::MyFrame( const wxString& title, const wxPoint& pos, const wxSize& size )
: wxFrame( (wxFrame*) NULL, -1, title, pos, size )
{
	wxGrid* grid = new wxGrid( this, wxID_ANY );
	grid->CreateGrid( 20, 10 );
	grid->AutoSizeColumns( false );

	wxButton* button1 = new wxButton( this, wxID_ANY, "button1" );
	wxButton* button2 = new wxButton( this, wxID_ANY, "button2" );
	wxButton* button3 = new wxButton( this, wxID_ANY, "button3" );
	wxButton* button4 = new wxButton( this, wxID_ANY, "button4" );

	wxBoxSizer* horizontalBoxSizer = new wxBoxSizer( wxHORIZONTAL );

	horizontalBoxSizer->Add( button1, 1 );
	horizontalBoxSizer->Add( button2, 1 );
	horizontalBoxSizer->Add( button3, 1 );
	horizontalBoxSizer->Add( button4, 1 );

	wxBoxSizer* verticalBoxSizer = new wxBoxSizer( wxVERTICAL );
	verticalBoxSizer->Add( grid, 1, wxEXPAND );

	verticalBoxSizer->Add( horizontalBoxSizer, 0, wxEXPAND );

	SetSizer( verticalBoxSizer );
	verticalBoxSizer->Layout();
	verticalBoxSizer->Fit( this );

	grid->AutoSize();
}
but the result is still the same.
It does not even blow the last colums up to the free space. But that is anyway not what i want.
Seems like i have to read a bit more about sizers and spacers and create something more nested.
Thank you nevertheless.

Posted: Thu Sep 17, 2009 11:21 am
by catalin
Dobias wrote:Seems like i have to read a bit more about sizers and spacers and create something more nested.
Thank you nevertheless.
As I see it, this is not about sizers and spacers since the white space that you see is part of the wxGrid (see the grey area at the top - that is the [most obvious] proof).
So it behaves correctly when added to the sizer. There is a problem with resizing its columns thowgh - something internal to wxGrid.
My advice would be to check the sources for something that works different than the way you'd expect.

Anyway, good luck!

Posted: Thu Sep 17, 2009 1:41 pm
by Dobias
Thanks.
The sizers-and-spacers-solution would be to nest the grid into spacers so that when the window grows the grid takes its optimal size as soon as posible but further space will be given to the spacer aside. But I don't know if this is actually possible. ;-)