Wxsmith tutorial: Working with items
Warning: Unfinished
Adding new resources into project
Hi. In the previous tutorial we learned how to create some small application using wxWidgets. We created window with few items inside. In this tutorial we will focus on wxWidgets items which form the resource. I'll show how you can add items into resource, how to change them, finally I'll describe few most important and most usefull items.
Note that all screenshoots presented here were made on Linux but it shoul not be very different from windows version.
Ok, let's start.
Create new application
We will start with empty wxWidgets project as our blackboard. Steps required to do this were described in previous tutorial so if you have any problems you can look into it.
Let's select File->New->Project menu, and choose wxWidgets application there. When you're in the wizard, make sure that "Preffered GUI Builder" is set to wxSmith and "Application type" is set to "Frame Based".
After the wizard generates project you should be able to compile and run it. The application should look like this:
This screenshoot was taken on linux. On windows it will have same buttons, but they may be ordered differently.
Few words about available sizers
As in previous tutorial we will focus on sizers to layout our window. Currently we know that sizers are responsible for automatically setting position and size of some components. But how they do that? Well it depends on which sizer has been used. The genric rule is that sizer tries to use all it's available space and place managed components in such way that they do not overlap. If the area available to sizer is to small, it requests bigger area so you can be sure that all components will be placed on the window (unfortunately you can not be sure that the window will be small enough to fit on the screen though so be careful with that). Another rule which should be mentioned here is that sizers automatically set-up the minimum size required by the window. Basically when you edit window using sizers, you should know that you edit the smallest layout and without some tricks, the generated you won't be able to resize window to something smaller.
Next I'll describe sizers available in wxSmith
wxBoxSizer
wxBoxSizer is the most basic sizer available in wxWidgets. It's purpose is to align components in one line - one next to another - either horizontally or vertically. This sizer also tries to keep some proortions between components - for horizontal sizer you can set factors which will keep proportionality of the width and the height of the sizer area will be equal to height of the tallest component. Analogically, vertical sizers keep height proportional and the width will be the widest one.
Here are examples of layout using box sizers (the first one is the horizontal one, the second is vertical one):
In that example you may see that all somponents have same width and height. But let's assume that we want the Button2 to be 2 times wider that Button1 and Button3 to be 3 times wider than Button1. This can be easily done by using the Proportion property of managed components. By default the value of all components is set to 1. So if we have 3 buttons, all with proportion equal to 1, it means that they should keep the proportions 1:1:1. If you set Proportion of second button to 2, it would mean that they should keep proportions 1:2:1 (the button in the middle should be 2 times wider/higher than the others). Genreally you can set any value you want here. One of common techniques is to set percentage value there - for example setting proportions to values 20, 30 and 50 would mean that the first button should occupy 20% of the space, the second one should occupy 30% and the third one 50%. The special value 0 means that this item should not be simply skipped in proportion calculations and it will won't automatically adjust it's size.
So if we want to get 1:2:3 proportions, we set 1 for Button1, 2 for Button2 and 3 for Button3. And here are the results:
Also note that if you create resizable window and resize it, those 3 buttons will automatically grow and keep proportions (when you set Proportion to 0, such item won't grow).
The other dimension which is not controlled by Proportion property may be controlled using "Expand" and "Shaped" properties. They are simple checkbockses. If you check the first one, the item will expand it's width/height and will get the size of the biggest item managed by the same sizer. Selecting "Shaped" will also make the item resize but such item will try to keep the initial proportion between width and height so it don't have to use all the space. The effect of "Expand" and "Shaped" properties can be seen when items differ in width/height, here's the example:
In this examples, the first button is the one that has the biggest size of all three buttons. It's size will be used to adjust sizes of other buttons. The second one has "Expand" flag enabled and the third one does not. What can be seen here is that the third button did expand only in one dimension (the one managed by "Proportion" property), the second dimension was left untouched.
You may also note that when item does not fit the entire area, it is centered. That's default behavior which can be changed. In properties of components managed by sizer you will find properties called Horizontal align and Vertical align. Using these properties you can select where the item should be located when it's smaller that it's available area.
wxStaticBoxSize
This sizer is simillar to wxBoxSizer with one exception: it adds extra static box around managed items:
wxGridSizer
This sizer is little bit more advanced than wxBoxSizer because it does align items on grid, not on line. You can specify number of columns or number of rows in properties "Cols" and "Rows". By default number of columns is set to 3 and number of rows is set to 0. When 0 is used, it does mean that sizer should automatically calculate this value to keep all managed components inside.
Also note that there's one assumption in wxWidgets - all columns have same width and all have same height. This mean that the tallest managed item will set the height of all rows and the widest one will set the widthts of all columns. In propreties of wxGridsizer you can also find horizontal and vertical spacings. These values set the spacing added between items. The result of using them is simillar for using borders around managed components but you would have to set borders for all items separately.
In case of wxGridSizer, the "Proportion" value is not used. But you may use "Expand", "Shaped" or placement properties to adjust the result.
Here's an example of grid sizer:
wxFlexGridSizer
This is one of the very usefull one. It works simillarily to wxGridSizer but it does not force all columns/rows to have same width/height. Also not all comuns do resize when there's more space available for the sizer. Comparing to wxGridSizer you will find two extra properties here: "Growable cols" and "Growable rows". In these properties you may provide list of columns / rows which should automatically resize (very usefull to handle resizing of the window) by providing list of numbers separated using coma (,). Numbers should start from 0, so if you would like second and third columnt to resize, put "1,2" into "Growable cols". But you won't be able to set proportions other that 1:1 ("Proportion" property is also not used in this sizer).
wxStdDialogButtonSizer
This is the specialized sizer with one purpose - provide set of standard buttons with respect to platform's look and feel. This sizer has predefined list of components which it can handle - all are buttons and you can manage them using sizer's properties. You can not add your custom items into this sizer.
Each button on this sizer has two properties in sizer - whether button should be enabled (for example wxID_OK for OK button) and it's label. Note that labels for most buttons will be generatede automatically and wxWidgets will skip them when it would be able to read them from system settings (for example on linux only the Context Help button does not have label). It's also very probable that labels will be provided with language-specific strings (depending on current system language). Not all configurations of buttons are valid - they won't break the application but buttons will overlap (for example yes and ok buttons).
Here's and example of the sizer (note that labels are in Polish and do mean: Help, Cancel, Apply and Ok):
This screenshoot was taken on linux box. On windows it would have same buttons but with different order.
All those sizers can be found on the "Layout" pallete page. You can find two other items there which are not sizers but can be used for layout purposes.
The first one is Spacer. It can be added to other sizer when you simply need some empty space instead of any particular component. Spacers have only width and height.
The second one is wxSplitterWindow. When you use this component, you can add one or two child components into it and they will be separated with dividing line (it's called sash in wxWidgets). You can drag it to dynamically adjust the size.