wxFlexGridSizer and wxDatePickerCtrl 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
Natulux
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 242
Joined: Thu Aug 03, 2017 12:20 pm

wxFlexGridSizer and wxDatePickerCtrl

Post by Natulux »

Hey guys

I've got another trivial problem that I seem not to be able to solve on my own. (wxWidgets 3.1.0)
Ive got a simple Dialog using wxFlexGridSizer for each line in my main panel.
But as you can see in the picture, the wxDatePickerCtrl is greedy and takes more of the resizeable space than it actually needs - it just doesn't look good:
UnFit.png
UnFit.png (3.16 KiB) Viewed 1602 times

Code: Select all

//Body Left - LINE2
mpn_bodyLeft_LINE2 = new wxPanel(mpn_bodyLeft);
mfgs_bodyLeft_LINE2 = new wxFlexGridSizer(2);
		
	wxPanel * pn_birthday = new wxPanel(mpn_bodyLeft_LINE2);
	wxFlexGridSizer * fgs_birthday = new wxFlexGridSizer(1);

		mst_Geburtsdatum = new wxStaticText(pn_birthday, wxID_ANY, "Geburtsdatum");
		mdpc_Geburtsdatum = new wxDatePickerCtrl(pn_birthday, ID_DATEPICKER_BIRTHDAY, dt, wxDefaultPosition, wxDefaultSize, wxDP_DROPDOWN);
					
		fgs_birthday->Add(mst_Geburtsdatum, 1, wxBOTTOM | wxEXPAND, 5);
		fgs_birthday->Add(mdpc_Geburtsdatum, 1, wxEXPAND, 0);
		fgs_birthday->AddGrowableCol(0, 1);
	pn_birthday->SetSizer(fgs_birthday);

	wxPanel * pn_salutation = new wxPanel(mpn_bodyLeft_LINE2);
	wxFlexGridSizer * fgs_salutation = new wxFlexGridSizer(1);

		mst_Anrede = new wxStaticText(pn_salutation, wxID_ANY, "Anrede");
		mch_Anrede = new wxChoice(pn_salutation, ID_CHOICE_SALUTATION);
								
		fgs_salutation->Add(mst_Anrede, 1, wxBOTTOM | wxEXPAND, 5);
		fgs_salutation->Add(mch_Anrede, 1, wxEXPAND, 5);
		fgs_salutation->AddGrowableCol(0, 1);
	pn_salutation->SetSizer(fgs_salutation);

	mfgs_bodyLeft_LINE2->Add(pn_birthday, 1, wxRIGHT | wxEXPAND, 5);
	mfgs_bodyLeft_LINE2->Add(pn_salutation, 1, wxEXPAND, 0);
	mfgs_bodyLeft_LINE2->AddGrowableCol(0, 1);
	mfgs_bodyLeft_LINE2->AddGrowableCol(1, 1);
	mfgs_bodyLeft_LINE2->AddGrowableRow(0, 1);

mpn_bodyLeft_LINE2->SetSizer(mfgs_bodyLeft_LINE2);
I thought I could outsmart the sizer by stuffing the DateCtrlPicker into its own panel and sizer and make this panel and the other panel both AddGrowableCol with proportion 1, so that the DatePickerCtrl just does not have all the space to grow into. But it seems to be the other way around - all panels are asking their ctrls how much space they should take. I want the FlexGridSizer to arrange all the sizes for me and therefore don't set any sizes on my own.
In other words: It makes no difference, if I add the ctrl directly or if I give it its own sub-panel and sub-sizer.

I could think of resizing the panel on my own by getting the width of the whole thing, dividing it by 2 and set the width myself. But is there really no better option to deal with this?

Best
Natu
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by doublemax »

Why exactly do you have all these intermediate panels?
The main purpose of a grid sizer is that you can put all elements into one sizer and they will all align nicely in vertical direction.

I think you should have only one wxFlexGridSizer and put all controls into it.

Or better use wxGridBagSizer. It's a little more complicated to use, but very often you will encounter a situtation where you want to join a few cells vertically or horizontally. And only wxGridBagSizer can do that.
Use the source, Luke!
Nunki
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 235
Joined: Fri Sep 14, 2012 8:26 am
Location: Kontich, Belgium
Contact:

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by Nunki »

Hi Natu,

The simplest way is to start with a Horizontal sizer in which you place two vertical sizers. See the screenprint from Dialogblocks (Test2)
test2.png
test2.png (76.71 KiB) Viewed 1582 times
with regards,
Nunki
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by doublemax »

The simplest way is to start with a Horizontal sizer in which you place two vertical sizers.
Sorry, but that's a good example what you should not do and why you should use a grid based sizer.

If for some reason you wanted the first button to be a little higher, you will have a hard time to align the two buttons in the second row properly.
Use the source, Luke!
Natulux
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 242
Joined: Thu Aug 03, 2017 12:20 pm

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by Natulux »

doublemax wrote:Why exactly do you have all these intermediate panels?
I have each line in one panel and for each panel a sizer, because the whole dialog is a little more complicated than the snippet I showed you (sorry).
The lines are devided by different sizes throughout the dialog or at least I need to be able to realize different sizes if I am asked for it later. If I used a grid with fixed sizes, I couldn't build a custom layout like that as far as I know.
fullDialog.png
fullDialog.png (14.51 KiB) Viewed 1534 times
doublemax wrote:The main purpose of a grid sizer is that you can put all elements into one sizer and they will all align nicely in vertical direction.

I think you should have only one wxFlexGridSizer and put all controls into it.

Or better use wxGridBagSizer. It's a little more complicated to use, but very often you will encounter a situtation where you want to join a few cells vertically or horizontally. And only wxGridBagSizer can do that.
I'll have a look at the wxGridBagSizer, I haven't tried that one. If it helps in this special situation, I might just use it for that line though.

[EDIT]:
From what I've seen, the GridBagSizer is an enhancement to the FlexGridSizer, trying to solve custom layouts with one sizer only. But having a more complicated sizer without an explanation or sample code is a bit painful for me.
At least I found an article on Stackoverflow, where someone is using it, even though it's python: https://stackoverflow.com/questions/232 ... idbagsizer

Thanks!
Natu
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by doublemax »

I'll have a look at the wxGridBagSizer, I haven't tried that one. If it helps in this special situation, I might just use it for that line though.
No, that wouldn't work. But it could create the whole layout with a single sizer.

With your current setup, i would try this (untested):
- put the wxDatePickerCtrl and wxChoice in an additional horizontal wxBoxSizer.
- when you create the controls, don't use wxDefaultSize, use an equal specific size for both
- set the proportion to 1 for both controls when adding to the sizer

I don't know if the same also works in a wxFlexGridSizer, but it may be worth a try before you make any bigger changes to the sizer structure.
Use the source, Luke!
Natulux
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 242
Joined: Thu Aug 03, 2017 12:20 pm

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by Natulux »

doublemax wrote:
I'll have a look at the wxGridBagSizer, I haven't tried that one. If it helps in this special situation, I might just use it for that line though.
No, that wouldn't work. But it could create the whole layout with a single sizer.
I think I can't yet say if it would work. I applied the new sizer to my LINE 2 panel, and almost reproduced the behavior I had before:

Code: Select all

//Body Left - LINE2
mpn_bodyLeft_LINE2 = new wxPanel(mpn_bodyLeft);
wxGridBagSizer * gbs_bodyLeft_LINE2 = new wxGridBagSizer(1, 1);
gbs_bodyLeft_LINE2->SetFlexibleDirection(wxBOTH);

	mst_Geburtsdatum = new wxStaticText(mpn_bodyLeft_LINE2, wxID_ANY, "Geburtsdatum");
	mdpc_Geburtsdatum = new wxDatePickerCtrl(mpn_bodyLeft_LINE2, ID_DATEPICKER_BIRTHDAY, dt, wxDefaultPosition, wxDefaultSize, wxDP_DROPDOWN);
				
	mst_Anrede = new wxStaticText(mpn_bodyLeft_LINE2, wxID_ANY, "Anrede");
	mch_Anrede = new wxChoice(mpn_bodyLeft_LINE2, ID_CHOICE_SALUTATION);

	gbs_bodyLeft_LINE2->Add(mst_Geburtsdatum, wxGBPosition(0, 0), wxGBSpan(1,1), wxRIGHT | wxBOTTOM | wxEXPAND, 5);
	gbs_bodyLeft_LINE2->Add(mst_Anrede, wxGBPosition(0, 1), wxGBSpan(1, 1), wxBOTTOM | wxEXPAND, 5);
	gbs_bodyLeft_LINE2->Add(mdpc_Geburtsdatum, wxGBPosition(1, 0), wxGBSpan(1, 1), wxRIGHT | wxEXPAND, 0);
	gbs_bodyLeft_LINE2->Add(mch_Anrede, wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND, 5);
				
	gbs_bodyLeft_LINE2->AddGrowableCol(0, 1);
	gbs_bodyLeft_LINE2->AddGrowableCol(1, 1);
	gbs_bodyLeft_LINE2->AddGrowableRow(0, 1);
								
mpn_bodyLeft_LINE2->SetSizer(gbs_bodyLeft_LINE2);
Without giving real sizes, the sizer does behave like FlexGridSizer, which doesn't really surprise me now, since the GridBagSizer is derived from it:
fullDialog_BagGrid.png
fullDialog_BagGrid.png (14.61 KiB) Viewed 1521 times
doublemax wrote:With your current setup, i would try this (untested):
- put the wxDatePickerCtrl and wxChoice in an additional horizontal wxBoxSizer.
- when you create the controls, don't use wxDefaultSize, use an equal specific size for both
- set the proportion to 1 for both controls when adding to the sizer

I don't know if the same also works in a wxFlexGridSizer, but it may be worth a try before you make any bigger changes to the sizer structure.
I will try that next. ;-)

Thanks!
Natu
Nunki
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 235
Joined: Fri Sep 14, 2012 8:26 am
Location: Kontich, Belgium
Contact:

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by Nunki »

doublemax wrote:
The simplest way is to start with a Horizontal sizer in which you place two vertical sizers.
Sorry, but that's a good example what you should not do and why you should use a grid based sizer.

If for some reason you wanted the first button to be a little higher, you will have a hard time to align the two buttons in the second row properly.
Ok, there you have a valid point ! I did not consider this based upon the little screenshot he made. In that case I would also go for a gridbag sizer. if needed with some vertical or horizontal sizers within.

regards,
Nunki
Natulux
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 242
Joined: Thu Aug 03, 2017 12:20 pm

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by Natulux »

doublemax wrote:With your current setup, i would try this (untested):
- put the wxDatePickerCtrl and wxChoice in an additional horizontal wxBoxSizer.
- when you create the controls, don't use wxDefaultSize, use an equal specific size for both
- set the proportion to 1 for both controls when adding to the sizer

I don't know if the same also works in a wxFlexGridSizer, but it may be worth a try before you make any bigger changes to the sizer structure.
I guess you had the right approach here. I don't think that there is a big difference in how any of the sizers calculates element sizes, if wxDefaultSize is given. But when I made an educated guess about the size and still make it GrowableCol, I get what I want.
I used the code from my first post, using wxFlexGridSizers but adding a size:

Code: Select all

mdpc_Geburtsdatum = new wxDatePickerCtrl(pn_birthday, ID_DATEPICKER_BIRTHDAY, dt, wxDefaultPosition, wxSize(100, 23), wxDP_DROPDOWN);
//[...]
mch_Anrede = new wxChoice(pn_salutation, ID_CHOICE_SALUTATION, wxDefaultPosition, wxSize(100, 23));
rightSize.png
rightSize.png (4.55 KiB) Viewed 1511 times
I guess I should add

Code: Select all

mfgs_main->Layout();
... at the end and then set the the initial size (or at least the height) according to the size of the other elements. (and call Layout again I think)
[UPDATE]
Getting the sizes after Layout and applying it to these elements doesn't work as expected. I really need to go with that educated guess and take care, not to set fancy min sizes later on.

But I can go with that. Thanks again!
Natu
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by doublemax »

don't think that there is a big difference in how any of the sizers calculates element sizes, if wxDefaultSize is given.
Actually, there is.

Before wx 3.x:
If you have 2 items in a sizer, both with "proportion=1", they would get the same size

Since 3.x:
The minimum size for all controls is taken, and if there is additonal space, it gets distributed according to the proportions. This is probably want happened for you, i guess the wxDatePickerCtrl has a bigger initial minimum size than the button.

And now the size given to a control's constructor comes into play: if you pass a non-default size, that size will be implizitly set as the minimum size of the control. And if you pass the same value for all controls (doesn't even matter what size), you'll get the old pre 3.x behavior back.
Use the source, Luke!
Natulux
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 242
Joined: Thu Aug 03, 2017 12:20 pm

Re: wxFlexGridSizer and wxDatePickerCtrl

Post by Natulux »

doublemax wrote:
don't think that there is a big difference in how any of the sizers calculates element sizes, if wxDefaultSize is given.
Actually, there is.

Before wx 3.x:
If you have 2 items in a sizer, both with "proportion=1", they would get the same size

Since 3.x:
The minimum size for all controls is taken, and if there is additonal space, it gets distributed according to the proportions. This is probably want happened for you, i guess the wxDatePickerCtrl has a bigger initial minimum size than the button.

And now the size given to a control's constructor comes into play: if you pass a non-default size, that size will be implizitly set as the minimum size of the control. And if you pass the same value for all controls (doesn't even matter what size), you'll get the old pre 3.x behavior back.
That is quite interesting, actually. Some of the older projects I have to work with are wxWidgets 2.x, while all my newer ones are 3.x. I wonder if I really never had this problem, if I was still with wxWidgets 2.x.

There has got to be something special going on with the wxDatePicker, though. If you have a look at the first picture I provided, the DatePicker has bigger minimum than the wxChoice in Line1 (quite obviously), but so has the filled wxTextCtrl in Line 2 in comparison to the empty wxTextCtrl next to it - and the last two are perfectly equal in size.
I would guess, that it is due to the little icon to the right of the DatePicker, which maybe adds its minimum to the parent after the sizer has distributed the space left. I feel like wxDefaultSize should take care of that and leave the sizing to the proportion only, if there is enough space for everything to show. At least for me it is not intuitive, that I should provide sizes to my elements, even though I want them to be resized always and automatically. I don't yet see an improvement in the behavior of wxWidgets 3.x in this matter.

[EDIT]
Might also be the little arrow on the right of wxChoice, though, which in this case would not add its minimum to the parent, but instead take some of it. I could test this, if I give each of them a TextCtrl to work with and see which one is off.

[EDIT2]
What? I stop guessing now:
iDunno.png
iDunno.png (4.12 KiB) Viewed 1481 times
Best
Natu
Post Reply