Difference between revisions of "Wxsmith tutorial: Working with items"

From Code::Blocks
(Fixed minor grammar, spelling and typing errors and reworded for clarity)
 
(29 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 
[[Category:wxSmith Documentation]]
 
[[Category:wxSmith Documentation]]
 +
= Working with Menus and Components =
  
 +
In the [[wxSmith tutorial: Hello world|previous tutorial]] we learned how to create a small application using wxWidgets. We created a window with a few components inside. In this tutorial, we will first see how to use the menu bar at the top of the main window and then focus on sizers and wxWidgets components which can be put on a form or window.
  
= Working with items =
+
----
  
Hi. In the [[wxSmith tutorial: Hello world|previous tutorial]] we learned how to create a small application using wxWidgets. We created a window with a few items inside. In this tutorial we will focus on wxWidgets items which form a resource. I'll show how you can add items into a resource, how to change them, and finally I'll describe a few of the most important and most useful items.
+
'''A Note on Terminology'''
 +
 
 +
BYO, the creator of wxSmith and original author of these tutorials, wrote "Each resource in wxSmith is made of items. All your buttons, text boxes, lists etc are items. Also some more abstract things like sizers, spacers (used to add empty space), menu entries or even timers are also called items in wxSmith. So basically anything that's inside the resource may be called an item. I'll also use the term component since it reflects the valid meaning too."
 +
 
 +
In fact, the word "item" is not found in the index of the Julian Smart and Kevin Hock book ''Cross-Platform GUI Programming with wxWidgets.'' The word is used in the book specifically for the elements of the drop-down lists of choice boxes, combo boxes, and other members of the class wxControlWithItems. In the revision of these tutorials, the word "item" is therefore generally being reserved for items in these lists and for items in a menu. Otherwise, the word "item" is generally being replaced by "component", "widget", or "control" as seems appropriate, though of course, it is also occasionally used with no special technical meaning. Also, BYO often uses the word "resource" to refer to a form or window. Smart and Hock use word the "resource" sparingly, mainly in the context of "resource files".  The word seems overworked and needlessly abstract, so when what is intended is a form or window, the revisions will use one of those words, with no sharp distinction between them.  
 +
 
 +
----
  
 
Note that all screenshots presented here were made on Linux but they should not be very different from the windows ones.
 
Note that all screenshots presented here were made on Linux but they should not be very different from the windows ones.
  
Ok, let's start.
+
== Working with Menus ==
 +
 
 +
Following the directions given in Tutorial 1, start a new Code::Blocks project; call it Tutorial_2. Remember to add "event.Skip(TRUE);" at the appropriate place in the code, as explained in Tutorial 1.
 +
 
 +
Build and run the program. You will see that it has two items on the main menu. We will add one more, Jump, at the top level and under it two more, Back and Out. Back will do nothing, but we will make Out close the program.
 +
 
 +
Click on the “Tutorial_2frame.wxs” tab of the Editor window.  Just below the words “Tutorial_2framw.wxs” is a panel with two square icons.  Double left click on the leftmost one, which shows the word ''File'' suggestive of a menu.  Up comes the menu inspector window shown below.
 +
 
 +
[[Image:1i.png]] 
 +
 
 +
Click on the various menu items shown and note how the content of the fields shown on the right side of the window are filled in.  Then click on the New button (in the lower right part of the window) to add the three additional menu items mentioned above, namely Jump at the top level and under it Back and Out. It does not matter where the items first appear; you use the arrow keys just above the “New” and “Delete” buttons to move around the item you have selected.  For the “Id” field of the “Out” item, put idMenuOut. You should make the menu inspector window look like this:
 +
 
 +
[[Image:1j.png]]
 +
 
 +
 
 +
When you have the menu items properly arranged, click OK.  
  
== Create new application ==
+
When you now build and run, you will see the new menu.  But clicking Jump | Out  does not close the program as desired because we have not programmed the response to that event.  To do so, we want to make wxSmith set up the frame for the routine which will be called when the menu item “Out” is clicked.  Go to the Management pane, Resources tab and persistently click on the little right-pointing triangles until the “Out” item can be seen, as in the screen shot below.
  
We will start with empty wxWidgets project as our blackboard. Steps required to do this were described in [[wxSmith tutorial: Hello world|previous tutorial]] so if you have any problems you can look into it.
+
[[Image:1k.png]]
  
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'''.
+
     
 +
Click on the word “Out” and then on the {} icon in the panel below the Management pane. That will cause the pane below to show the words “EVT_MENU    --None--” . Click on the word “None” or the down arrow at the right end of the field; a menu drops down.  Pick the item  “-- Add New Handler --”, accept the suggested name (OnMenu3Selected), and over in the editor, the frame of our handler has been written, as shown below.  We have only to write the code, which will be simply “Close();”.
  
After the wizard generates a new project you should be able to compile and run it. The application should look like this:
+
[[Image:1l.png]]
  
[[Image:wxs_tut02_001.png]]
+
Now we can “Build and run”, drop down our menu, click on “Out”, and the program closes, as desired.
  
== Working with items ==
+
== Windows and Components ==
  
  
Each resource in wxSmith is made of items. All your buttons, text boxes, lists etc are items. Also some more abstract things like sizers, spacers (used to add empty space), menu entries or even timers are also called items in wxSmith. So basically anything that's inside the resource may be called an item. I'll also use the term component since it reflects the valid meaning too.
+
Each window in wxSmith is made of components. All your buttons, text boxes, lists, and so on are components. Also some more abstract things like sizers, spacers (used to add empty space), menu entries or even timers are also components.
  
Actually each resource has one root item: for dialog window it would be wxDialog item, for frame window it would be wxFrame item and simillarily for panel it would be wxPanel item. If you walked through [[wxSmith tutorial: Hello world|previous tutorial]] you probably noticed that some items may have children - for example you insert sub-menus into menus, some items into sizers and so on. Those items may also have their children. This forms a structure of tree which is directly represented inside resource browser:
+
Every window has a root component. For a dialog window, it would be a wxDialog component; for a frame window, it would be wxFrame component; for a panel it would be a wxPanel component. In the [[wxSmith tutorial: Hello world|previous tutorial]] you probably noticed that some components may have "children". For example, sizers had components inside their boxes. In this tutorial, you have seen sub-menu items inside main-menu items. The term "children" suggests the idea of a family tree, and indeed precisely such a tree structure is directly represented in the resource browser, as shown in the example below.
  
 
[[Image:wxs_tut02_008.png]]
 
[[Image:wxs_tut02_008.png]]
  
In the picture above, you will see an example of such a tree. wxFontFaceEditorDlg is the currently opened resource with a root node of type wxDialog. We can see that this resource consists of a few sizers and buttons, one text area and some spacers. It's definitely a very simple resource. For more complicated resources, there could be more than 100 items and the tree browser may be helpful when locating them inside the editor.
+
In the picture above, you will see an example of such a tree. wxFontFaceEditorDlg is the currently opened form with a root component of type wxDialog. We can see that this resource consists of a few sizers and buttons, one text area and some spacers. It's definitely a fairly simple form. For more complicated forms, there could be more than 100 components. The tree (or Resource) browser can be very helpful for locating the code connected with a component; clicking on the component in the browser brings up its code in the editor.
  
Each item has its properties - these are usually some values which describe the item. Some of them may affect the way item looks, some may change the item's behavior, and some may be dedicated to programming facilities. You will also find that there is a set of properties available for almost every item - that's correct since many properties are generic like position and size.
+
Each component has its properties - these are usually some values which describe the component. Some of them may affect the way component looks, some may change the component's behavior, and some may be dedicated to programming facilities. You will also find that there are some properties -- such as position and size -- common to many components.
  
wxSmith allow you to edit items inside the properties browser (the window which is usually under the resource browser). If you select an item either by selecting it in the resource browser or by clicking on it inside editor, the properties editor switches to edit its properties. Here's an example of the property browser:
+
wxSmith allows you to edit components inside the properties browser (the window which is usually under the resource browser). If you select a component either by clicking on it in the resource browser or by clicking on it inside the editor, the properties editor switches to edit its properties. Here's an example of the property browser:
  
 
[[Image:wxs_tut02_009.png]]
 
[[Image:wxs_tut02_009.png]]
Line 42: Line 66:
 
[[Image:wxs_tut02_010.png]]
 
[[Image:wxs_tut02_010.png]]
  
The purpose of this panel is to provide most common properties in user-friendly way. Unfortunately it's rarely used in wxSmith now and you will probably find it useful only while adjusting sizer-related settings.
+
The purpose of this panel is to provide most common properties in user-friendly way. It hasn't proven as useful as I had hoped, and you will probably find it helpful only while adjusting sizer-related settings.
  
The last and the easiest one is to operate directly on item inside editor - you can grab drag boxes and change item's size. You can also move item into another position by simply dragging the item into another place.
+
The last and the easiest way to work on a component is directly in the editor. You can grab drag boxes and change the component's size. You can also change its position by simply dragging it to another place.
  
=== Excercise: playing with items ===
+
=== Excercise with Components ===
  
Ok, let's do some excercise. We started with empty window. First let's add wxFlexGridSizer into it - it's located in Layout pallete (you can find informations on how to add items in [[wxSmith tutorial: Hello world|previous tutorial]]). Now let's add following items into it adding each one after the previous: wxButton, wxStaticText, wxTextCtrl, wxRadioButton and wxCheckBox. The result should look like this:
+
Enough generalities; let's play with components. We can continue with the project started at the beginning of this tutorial. First let's add wxFlexGridSizer into our window. Like all sizers, it is located in Layout tab. (You'll remember how to add components from the [[wxSmith tutorial: Hello world|previous tutorial]]). Now let's add the following components into the sizer in the order given: wxButton, wxStaticText, wxTextCtrl, wxRadioButton and wxCheckBox. They can all be found on the Standard tab. The result should look like this:
  
 
[[Image:wxs_tut02_011.png]]
 
[[Image:wxs_tut02_011.png]]
  
I've selected added items with light red border on the palette - all can be found on Standard category.
+
In this picture, components I've selected have a light red border.
  
Now as we have our playground, let's change some items. First thing we will do is to change label and colour of the button. To do this let's click on it and move to properties window.
+
Now that we have our playground, let's change some components. First, let's change the label and color of the button. To do so, click on the button and move to the properties browser. "Label" is the first property, and it's quite easy to change. Just click on the word "Label" on the right and type new text.
  
Label is the first property and it's quite easy to change - you can do it by clicking on the "Label" on the right and just typing new text.
+
Color is little bit harder to find. Usually components have two colors - Background and Foreground color. Background, as the name implies, is used to fill the component's background. Foreground, on the other hand, is used to paint some content onto the background. Note that there's no strict interpretation of these colors so you should experiment to find out their meaning. In wxButton, Background is what we want.
Colour is little bit harder to find. Usually items have two colours - Background and Foreground colour. Background, as the name says, is used to fill item's background, Foreground on the other hand is used to paint some content onto background. Note that there's no strict interpretation of these colours so you should experiment to find out their meaning. In button, Background is what we need.
+
So let's find the Background property. It's value can be changed by using combobox:
So let's find Background property - it's value can be changed by using combobox:
 
  
 
[[Image:wxs_tut02_012.png]]
 
[[Image:wxs_tut02_012.png]]
  
On the list you may find set of predefined system colours. When you choose one of them, they will be read from current system settings making you application compatible with system theme. There are also two special entries - Default (which means that we do not want to set our colour) and Custom. When you select Custom, wxSmith will open colour dialog where you can choose any colour you want. I have choosen light green and here's the result:
+
On the list you may find a set of predefined system colors. When you choose one of them, they will be read from the current system settings making your application compatible with the system theme. There are also two special entries - Default (which means that we do not want to set our color) and Custom. When you select Custom, wxSmith will open a color dialog where you can choose any color you like. I have chosen light green, and here's the result:
  
 
[[Image:wxs_tut02_013.png]]
 
[[Image:wxs_tut02_013.png]]
  
There are also other properties we could talk about, but the best way to learn them is to play with them, so I leave the discoveries to you :)
+
There are also other properties we could talk about, but the best way to learn them is to play with them, so I leave those discoveries to you.
  
Now let's use a mouse.
+
Now let's use the mouse.
  
Selected item have eight black boxes around it - these boxes can be used to change size of item. You will easily notice when mouse is over the black box because the cursor changes. So let's resize the wxTextCtrl (edit box):
+
The selected component will have eight black boxes -- drag handles -- around it. These boxes can be used to change the size of the component. You will easily notice when the mouse is over a handle because the cursor changes. Let's resize the wxTextCtrl (edit box):
  
 
[[Image:wxs_tut02_014.png]]
 
[[Image:wxs_tut02_014.png]]
  
You may see that resizing item will also change properties in browser - '''Default Size''' is unchecked now and '''Width''' and '''Height''' is set to required values. There's also other property which seems to be untouched - '''Size in Dialog Units''', which is also related to size. I'll explain it better:
+
You may see that resizing the component will also change properties in the browser - '''Default Size''' is unchecked now and '''Width''' and '''Height''' are set to required values. There's another property which seems to be untouched - '''Size in Dialog Units''', which is also related to size. I'll explain it a bit.
Ususally when you must specify size (or other size-related thing) you provide value in pixels. Alternatively you can specify values in unit called '''Dialog Unit'''. '''Dialog Unit'' is usually little bit bigger than one pixel and it's size depends of size of current font (actually it's size of font of some item's parent which does have a font). This is useful when you want some values to be proportional to size of text presented on window.
+
 
If you check '''Size in Dialog Units'', wxSmith will take care of it and sizes will be calculated in Dialog Units instead of pixels (although you will still be able to resize items naturally).
+
Usually when you must specify a size (or other size-related things) you provide a value in pixels. Alternatively you can specify values in a unit called a '''Dialog Unit'''. A '''Dialog Unit''' is usually a little bit bigger than one pixel and it's size depends on the size of the current font (actually it's the size of the font of some component's parent which has a font). This is useful when you want some values to be proportional to the size of text presented in the window.  
  
Now let's change position of radio box. Ok, but I've said that sizer is responsible for the positioning - that's right. We have limited possibilities to change position - inside one sizer we can only reorder items, for more complex resources we can also move item between two sizers and other areas where sizers do not apply.
+
If you check '''Size in Dialog Units'', wxSmith will take care of it and sizes will be calculated in Dialog Units instead of pixels (although, naturally, you will still be able to resize components).
Ok, back to our example, let's move the radio box to position where it would be right after the button. To do this click on the radio button and drag it onto button. When you start dragging you will notice that the area of sizer changed to blue colour - this is a helper to show you what will be the new parent of dragged item. When you move cursor onto button, half of it will become light-blue. This helper shows where new item will be placed - when the left half of pointed item is highlighted, dragged item will be added before it. When the right half is hightlighted, dragged item will be added after it. And when there's no highlighted item, new item will be added as the last child of the parent:
+
 
 +
Now let's change the position of the radio box. "But, wait," you may say, "I thought you said that the sizer is responsible for the positioning." That's right. We have limited possibilities to change position. Inside one sizer we can only reorder components; for more complex forms we can also move a component between two sizers or to areas where sizers do not apply. So, back to our example, let's move the radio box to position it right after the button. To do so, click on the radio button and drag it onto the button. When you start dragging, you will notice that the area of the sizer changes color to blue. This color change is an aid to show you what will be the new position of the dragged component. When you move the cursor onto the button, half of the button will become light-blue. When the left half is highlighted, the dragged component will be added before it. When the right half is highlighted, dragged component will be added after it. And when there's no highlighted component, the new component will be added as the last child of the parent:
  
 
[[Image:wxs_tut02_015.png]]
 
[[Image:wxs_tut02_015.png]]
  
When you drop the item, it will change it's position. Note that all the items after the new position also moved - that's correct because default settings of wxFlexGridSizer allow only 3 items in one row (this can be changed in property browser) so the items just adapted to the new order:
+
 
 +
When you drop the component, it will change it's position. Note that all the components after the new position also shift. That happens because the default setting of the wxFlexGridSizer allows only 3 components in one row (this can be changed in property browser) so the components just adapted to the new order.
  
 
[[Image:wxs_tut02_016.png]]
 
[[Image:wxs_tut02_016.png]]
  
 +
==Sizers==
  
 +
Now let's learn a little bit about components available in wxSmith. I'll describe all supported sizers and a few important components from the Standard palette. Let's start with sizers.
  
Now let's learn a little bit about items available in wxSmith. I'll describe all supported sizers and a few important components from the Standard palette. Let's start with sizers.
+
We already know that sizers are responsible for automatically setting the position and size of some components. But how do they do that? Well, it depends on which sizer has been used. So what are the rules? The generic rule is that the sizer tries to use all its available space and place the components it manages in such way that they do not overlap. If the area available to the sizer is too small, it requests a bigger area, so you can be sure that no component will fall out of the window. (Unfortunately, you cannot be sure that after such adjustments the window will be small enough to fit on the screen, so be careful about 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 a window using sizers, you should be aware that you edit the smallest layout and without some tricks, you won't be able to resize the window to something smaller.
 
 
== A few words about available sizers ==
 
 
 
Currently we know that sizers are responsible for automatically setting position and size of some components. But how do they do that? Well it depends on which sizer has been used, so what are the rules? The generic rule is that the sizer tries to use all its available space and place managed components in such way that they do not overlap. If the area available to the sizer is too small, it requests a bigger area, so you can be sure that no component will fall outside of the window (unfortunately you can not be sure that after such adjustments the window will be small enough to fit on the screen 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 be aware that you edit the smallest layout and without some tricks, you won't be able to resize window to something smaller.
 
  
Here's list of all sizers available in wxSmith:
+
Here are descriptions of all sizers available in wxSmith:
  
 
=== wxBoxSizer ===
 
=== 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 widths and the height of the sizer area will be equal to height of the tallest component. Analogically, vertical sizers keep heights proportional and the width will be taken the widest component.
+
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 proportions between components - for a horizontal sizer you can set factors which will keep proportionality of widths and the height of the sizer area will be equal to the height of the tallest component. Similarly, vertical sizers keep heights proportional and the width will be taken from the widest component. You specify whether the sizer is to be horizontal or vertical in the sizer's property browser.
  
 
Here are examples of layout using box sizers (the first one is the horizontal one, the second is vertical one):
 
Here are examples of layout using box sizers (the first one is the horizontal one, the second is vertical one):
Line 106: Line 129:
  
  
In that example you may see that all components have same width and height.
+
In that example you may see that all components have the 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 they have equal size. Changing the Proportion of second button to 2 would mean that it should be 2 times wider that the first or third one.
+
But let's assume that we want Button2 to be two times wider that Button1 and Button3 to be three 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 they have equal size. Changing the Proportion of second button to 2 would mean that it should be 2 times wider than the first or third one.
  
Generally you can set any value you want here. One of common techniques is to set percentage value - 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 30% and the third one 50%. The special value 0 means that this item should be skipped in proportion calculations and it will won't automatically adjust it's size when main window is resized.
+
Generally you can set any value you want here. One common technique is to set percentage values - 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 30% and the third one 50%. The special value 0 means that this component should be skipped in proportion calculations and it won't automatically adjust it's size when the main window is resized.
  
 
So if we want to get 1:2:3 proportions, we set 1 for Button1, 2 for Button2 and 3 for Button3. And here is the result:
 
So if we want to get 1:2:3 proportions, we set 1 for Button1, 2 for Button2 and 3 for Button3. And here is the result:
Line 116: Line 139:
 
[[Image:wxs_tut02_003.png]]
 
[[Image:wxs_tut02_003.png]]
  
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).
+
Also note that if you create a resizable window and resize it, those 3 buttons will automatically grow and keep proportions. If you set the Proportion property for some component to 0, it won't change size as the user changes the size of the window.  
  
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 available space. The effect of "Expand" and "Shaped" properties can be seen when items differ in width/height, here's the example:
+
The other dimension which is not controlled by the "Proportion" property may be controlled using the "Expand" and "Shaped" properties. They are simple checkboxes. If you check the first one, the component will expand it's width/height and will get the size of the biggest component managed by the same sizer. Selecting "Shaped" will also make the component resize but such components will try to keep the initial proportion between width and height so it doesn't have to use all available space. The effect of the "Expand" and "Shaped" properties can be seen when components differ in width or height; here's an example:
  
 
[[Image:wxs_tut02_004.png]]
 
[[Image:wxs_tut02_004.png]]
  
In this example, 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.
+
In this example, the first button is the biggest of the three. Its size will be used to adjust the sizes of the other buttons. The second one has its "Expand" property checked, and the third one does not. What can be seen here is that the third button expanded in only 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.
+
You may also note that when a component does not fill its available area, it is centered. That's default behavior which can be changed. In the properties of components managed by sizer you will find properties called '''Horizontal align''' and '''Vertical align'''. Using these properties you can select where the component should be located when it's smaller that its available area.
  
 
=== wxStaticBoxSizer ===
 
=== wxStaticBoxSizer ===
  
This sizer is simillar to wxBoxSizer with one exception: it adds extra static box around managed items:
+
This sizer is similar to wxBoxSizer with one exception: it adds an extra static box around managed components:
  
 
[[Image:wxs_tut02_005.png]]
 
[[Image:wxs_tut02_005.png]]
Line 134: Line 157:
 
=== wxGridSizer ===
 
=== wxGridSizer ===
  
This sizer is little bit more advanced than wxBoxSizer because it does align items on grid, not on one 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.
+
This sizer is a little bit more advanced than wxBoxSizer because it aligns components on a grid, not on one line. You can specify the number of columns or number of rows in properties "Cols" and "Rows". The default number of columns is set to 3 and number of rows is set to 0. When 0 is used, it means that sizer should automatically calculate this value to keep all managed components inside.
  
Also note that there's one assumption in wxWidgets - all cells must have same width and all must 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. If item won't use whole cell, it will be surrounded by empty space.
+
This sizer makes an important assumption: all cells must have the same width and all must have the same height.  This means that the tallest managed component will set the height of all rows and the widest one will set the widths of all columns. If an component won't use the whole cell, it will be surrounded by empty space. (If you don't like this assumption, look at the wxFlexGridSizer.)
  
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 to using borders around managed components but with borders you would have to set borders for all items separately.
+
Among the properties of a wxGridSizer you can also find horizontal and vertical spacings. These values set the spacing added between components. The result of using them is similar to using borders around managed components but with borders you would have to set borders for all components separately.
  
In case of wxGridSizer, the "Proportion" value is not used. But you may use "Expand", "Shaped" or placement properties to adjust the result.
+
In the 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:
+
Here's an example of a grid sizer:
  
 
[[Image:wxs_tut02_006.png]]
 
[[Image:wxs_tut02_006.png]]
 
  
 
=== wxFlexGridSizer ===
 
=== wxFlexGridSizer ===
  
This is one of the very useful 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 useful 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 column to resize, put "1,2" into "Growable cols".  
+
This is a very useful one. It works similarly to wxGridSizer; but it does not force all columns to have the same width nor all rows to have the same height. Also not all columns 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 a list of columns / rows which should automatically resize by providing a list of numbers separated using comma (,). The numbers should start from 0, so if you would like the second and third column to resize, put "1,2" into "Growable cols". This property is very useful to handle resizing of the window.
 
 
Unfortunately you won't be able to set proportions other that 1:1 ("Proportion" property is also not used in this sizer).
 
  
 +
Unfortunately you won't be able to set proportions other that 1:1 The "Proportion" property is also not used in this sizer.
  
 
=== wxStdDialogButtonSizer ===
 
=== 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.
+
This is a specialized sizer with one purpose - to provide a set of standard buttons with respect to the platform's look and feel. This sizer has a predefined list of components which it can handle - all are buttons and you can manage them using the sizer's properties. You cannot add your custom components 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 generated automatically and wxWidgets will skip them when it would be able to read labels 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).
+
Each button on this sizer has two properties in the sizer - whether the button should be enabled (for example wxID_OK for OK button) and its label. Note that labels for most buttons will be generated automatically and wxWidgets will skip them when it can read them from the system settings. For example, on Linux only the Context Help button does not have a system-supplied label. It is also very probable that labels will be provided with language-specific strings (depending on the 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).
  
Here's and example of the sizer (note that labels are in Polish and do mean: Help, Cancel, Apply and Ok):
+
Here is an example of this sizer. My system is set up in Polish, so the labels are automatically in Polish.  They mean: Help, Cancel, Apply and OK.
  
 
[[Image:wxs_tut02_007.png]]
 
[[Image:wxs_tut02_007.png]]
  
This screenshot was taken on linux box. You may see that buttons have some extra image which is not available for standard buttons. With such layout, users of the application will feel more comfortable and such 'small' things make users say that the GUI was designed very well ;). On windows the sizer would have same buttons but without images and they would be in different order - the one that is used on windows by default.
+
This screenshot was taken on a Linux box. You may see that the buttons have an extra image which is not available for standard buttons. With such a layout, users of the application will feel more comfortable, and such 'small' things make users say that the GUI was designed very well. On MS Windows, the sizer would have the same buttons but without images and they would be in a different order - the one that is used on windows by default.
  
 +
All of the above sizers can be found on the "Layout" tab. You can find two other components there which are not sizers but can be used for layout purposes.
  
 +
The first one is Spacer. It can be added to other sizers when you simply need some empty space instead of any particular component. Spacers have only width and height.
  
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 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 a dividing line (it's called a sash in wxWidgets). On the application you can drag it to dynamically adjust the size of managed components.
  
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.
+
Now that we know something about sizers let's turn to other components.
  
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). On the application you can drag it to dynamically adjust the size of managed items.
+
== Especially Useful Standard Components ==
  
Now since we know something about sizers let's talk about other components.
+
wxWidgets provides all standard graphical components like static text, buttons, edit boxes, combo boxes, and so on. All are supported in wxSmith, so you can build a nice working environment. I'll briefly describe the components that are really useful in standard applications.
 
 
== Useful components ==
 
 
 
wxWidgets provides all standard graphical components like static texts, buttons, edit boxes - all those are supported in wxSmith so you can build a nice working environment. I'll shortly describe those that are really useful in standard applications.
 
  
 
=== wxButton ===
 
=== wxButton ===
Line 184: Line 203:
 
[[Image:wxs_tut02_017.png]]
 
[[Image:wxs_tut02_017.png]]
  
This is standard button, very common component. Its main purpose is to fire some event when you click on it and that's it.
+
This is standard button, a very common component. Its purpose is to run some piece of code when the user clicks on it. That's it.
  
 
=== wxStaticText ===
 
=== wxStaticText ===
Line 190: Line 209:
 
[[Image:wxs_tut02_018.png]]
 
[[Image:wxs_tut02_018.png]]
  
This item only shows user-defined text on the window. It don't generate any events.
+
This component only shows user-defined text on the window. It doesn't generate any events.
  
 
=== wxTextCtrl ===
 
=== wxTextCtrl ===
Line 196: Line 215:
 
[[Image:wxs_tut02_019.png]]
 
[[Image:wxs_tut02_019.png]]
  
This item let's user enter some text. It's basic functinality allow to enter one-line text. After changing it's properties it may become more advanced multiline editor with support for different fonts, colours and text styles.
+
This component let's the user enter some text. It's basic functionality allows entering one-line text. After changing its properties, it may become a more advanced multiline editor with support for different fonts, colors and text styles.
  
 
=== wxPanel ===
 
=== wxPanel ===
Line 202: Line 221:
 
[[Image:wxs_tut02_020.png]]
 
[[Image:wxs_tut02_020.png]]
  
Although this item may be separate resource, it can also be added as other resource's component. This item may be used as background for other components. It has few functionalities - it can be used as background in notebooks and it may be a place where you put items without sizers. But it also has few drawbacks - wxWidgets tends to do some tricks with wxPanel's size so it's not always possible to set size we really want.
+
Although this component may be a separate window, it is most commonly added as a comoponent in a parent window. It is particularly useful as a background for other components. It has a few functionalities - it can be used as background in notebooks and it may be a place where you put components without sizers. But it also has a few drawbacks - wxWidgets tends to do some tricks with wxPanel's size so it's not always possible to set the size we really want.
  
 
=== wxChoice ===
 
=== wxChoice ===
Line 208: Line 227:
 
[[Image:wxs_tut02_021.png]]
 
[[Image:wxs_tut02_021.png]]
  
This item provides drop-down list with available options. It works simillar to wxComboBox but you can not enter your own value. It can be used in situations when user should use one of available options. Event is generated when user change selected item.
+
This component provides a drop-down list with available options. It works similarly to wxComboBox but the user cannot enter values. It can be used in situations when the user should use one of several available options. An event is generated when the user changes the selected component.
  
 
=== wxComboBox ===
 
=== wxComboBox ===
Line 214: Line 233:
 
[[Image:wxs_tut02_022.png]]
 
[[Image:wxs_tut02_022.png]]
  
This item provides drop-down list simillarily to wxChoice. In case of this item, user can select one of available values or enter his own if the item is not in Read-Only state. Very good example of it's usage is to provide some text entry with stored list of previously entered values (like in search boxes). Simillarily to wxChoice, changing selection generates event. Additinoally changing the text and pressing enter also generates events.
+
This component provides a drop-down list similar to that of wxChoice. In the case of this component, the user can select one of the available values or enter his own if the component is not in a Read-Only state. A very good example of its usage is to provide some text entry with a stored list of previously entered values (like in search boxes). Like wxChoice, changing the selection generates an event. Additionally, changing the text and pressing enter also generates events. Tutorial 9 will illustrate its use.  
  
 
=== wxListBox ===
 
=== wxListBox ===
Line 220: Line 239:
 
[[Image:wxs_tut02_023.png]]
 
[[Image:wxs_tut02_023.png]]
  
This item provides list where you can select one or more items. Changing item or double-clicking on it generates event.
+
This component provides a list where you can select one or more components. Changing the component or double-clicking on it generates an event.
  
 
=== wxNotebook ===
 
=== wxNotebook ===
Line 226: Line 245:
 
[[Image:wxs_tut02_024.png]]
 
[[Image:wxs_tut02_024.png]]
  
Notebook is very useful for complex resources since it groups content in form of tabs. Addintionally wxChoicebook and wxCombobook are also available but are not described here. Changing selected notebook generates two events: one when the page starts to change (before change) and one when the page finished changing (after change)
+
Notebook is very useful for complex resources since it groups content under tabs. Additionally, wxChoicebook and wxCombobook are also available but are not described here. Changing the selected notebook generates two events: one when the page starts to change (before change) and one when the page is finished changing (after change).
  
 
=== wxCheckBox ===
 
=== wxCheckBox ===
Line 232: Line 251:
 
[[Image:wxs_tut02_025.png]]
 
[[Image:wxs_tut02_025.png]]
  
Check box may be used to map boolean values, additionally 2-state box can also be generated (with values: yes/no/unspecified). Changing value emits event.
+
Check boxes may be used to map boolean values. Additionally, 2-state boxes can also be generated (with values: yes/no/unspecified). Changing the value emits an event.
  
 
=== wxRadioBox ===
 
=== wxRadioBox ===
Line 238: Line 257:
 
[[Image:wxs_tut02_026.png]]
 
[[Image:wxs_tut02_026.png]]
  
Radio box works simillarily to check boxes. The difference is that only one radiobox in group can be selected. Groups may be defined by using wxRB_GOUP style - radiobox which have this style set starts new group. Changing selected radiobox emits event.
+
Radio box works similarly to check boxes. The difference is that only one radiobox in a group can be selected. Groups may be defined by using wxRB_GROUP style. A radiobox which has this style set starts a new group. Changing the selected radiobox emits an event.
  
 
=== wxGauge ===
 
=== wxGauge ===
Line 244: Line 263:
 
[[Image:wxs_tut02_027.png]]
 
[[Image:wxs_tut02_027.png]]
  
This item also named Progress Bar can be used to show progress of some operation. It's very useful when doing some intensive operations (users may get frustrated when they do not see any change but only window which seems to hang-up).
+
This component, also called a Progress Bar, can be used to show the progress of some operation. It's very useful when doing some calculation intensive operations. It can prevent users from getting frustrated when they do not see anything happening on the screen but only a window which seems hung.
 
 
  
 +
<nowiki> * * * * </nowiki>
  
 +
That's the end of this tutorial. We will get more experience with these subjects in the following tutorials. But you can also learn a lot by experimenting: add components, change properties, resize, move. You may try adding sizers into other sizers, a very useful technique absolutely required for more complex forms. Join me for the next tutorial!
  
 +
----
  
That's the end of this tutorial. I presented some basic informations about available items. If you want to learn more, the best way to do it is to experiment: add items, change properties, resize, move. You may try adding sizers into other sizers - this is also very useful technique absolutely required for more complex resources.
+
<center>'''[[WxSmith tutorial: Hello world|Previous]] | [[WxSmith tutorials|Index]] | [[WxSmith tutorial: Building more complex window|Next]]'''</center>

Latest revision as of 12:51, 12 May 2013

Working with Menus and Components

In the previous tutorial we learned how to create a small application using wxWidgets. We created a window with a few components inside. In this tutorial, we will first see how to use the menu bar at the top of the main window and then focus on sizers and wxWidgets components which can be put on a form or window.


A Note on Terminology

BYO, the creator of wxSmith and original author of these tutorials, wrote "Each resource in wxSmith is made of items. All your buttons, text boxes, lists etc are items. Also some more abstract things like sizers, spacers (used to add empty space), menu entries or even timers are also called items in wxSmith. So basically anything that's inside the resource may be called an item. I'll also use the term component since it reflects the valid meaning too."

In fact, the word "item" is not found in the index of the Julian Smart and Kevin Hock book Cross-Platform GUI Programming with wxWidgets. The word is used in the book specifically for the elements of the drop-down lists of choice boxes, combo boxes, and other members of the class wxControlWithItems. In the revision of these tutorials, the word "item" is therefore generally being reserved for items in these lists and for items in a menu. Otherwise, the word "item" is generally being replaced by "component", "widget", or "control" as seems appropriate, though of course, it is also occasionally used with no special technical meaning. Also, BYO often uses the word "resource" to refer to a form or window. Smart and Hock use word the "resource" sparingly, mainly in the context of "resource files". The word seems overworked and needlessly abstract, so when what is intended is a form or window, the revisions will use one of those words, with no sharp distinction between them.


Note that all screenshots presented here were made on Linux but they should not be very different from the windows ones.

Working with Menus

Following the directions given in Tutorial 1, start a new Code::Blocks project; call it Tutorial_2. Remember to add "event.Skip(TRUE);" at the appropriate place in the code, as explained in Tutorial 1.

Build and run the program. You will see that it has two items on the main menu. We will add one more, Jump, at the top level and under it two more, Back and Out. Back will do nothing, but we will make Out close the program.

Click on the “Tutorial_2frame.wxs” tab of the Editor window. Just below the words “Tutorial_2framw.wxs” is a panel with two square icons. Double left click on the leftmost one, which shows the word File suggestive of a menu. Up comes the menu inspector window shown below.

1i.png

Click on the various menu items shown and note how the content of the fields shown on the right side of the window are filled in. Then click on the New button (in the lower right part of the window) to add the three additional menu items mentioned above, namely Jump at the top level and under it Back and Out. It does not matter where the items first appear; you use the arrow keys just above the “New” and “Delete” buttons to move around the item you have selected. For the “Id” field of the “Out” item, put idMenuOut. You should make the menu inspector window look like this:

1j.png


When you have the menu items properly arranged, click OK.

When you now build and run, you will see the new menu. But clicking Jump | Out does not close the program as desired because we have not programmed the response to that event. To do so, we want to make wxSmith set up the frame for the routine which will be called when the menu item “Out” is clicked. Go to the Management pane, Resources tab and persistently click on the little right-pointing triangles until the “Out” item can be seen, as in the screen shot below.

1k.png


Click on the word “Out” and then on the {} icon in the panel below the Management pane. That will cause the pane below to show the words “EVT_MENU --None--” . Click on the word “None” or the down arrow at the right end of the field; a menu drops down. Pick the item “-- Add New Handler --”, accept the suggested name (OnMenu3Selected), and over in the editor, the frame of our handler has been written, as shown below. We have only to write the code, which will be simply “Close();”.

1l.png

Now we can “Build and run”, drop down our menu, click on “Out”, and the program closes, as desired.

Windows and Components

Each window in wxSmith is made of components. All your buttons, text boxes, lists, and so on are components. Also some more abstract things like sizers, spacers (used to add empty space), menu entries or even timers are also components.

Every window has a root component. For a dialog window, it would be a wxDialog component; for a frame window, it would be wxFrame component; for a panel it would be a wxPanel component. In the previous tutorial you probably noticed that some components may have "children". For example, sizers had components inside their boxes. In this tutorial, you have seen sub-menu items inside main-menu items. The term "children" suggests the idea of a family tree, and indeed precisely such a tree structure is directly represented in the resource browser, as shown in the example below.

Wxs tut02 008.png

In the picture above, you will see an example of such a tree. wxFontFaceEditorDlg is the currently opened form with a root component of type wxDialog. We can see that this resource consists of a few sizers and buttons, one text area and some spacers. It's definitely a fairly simple form. For more complicated forms, there could be more than 100 components. The tree (or Resource) browser can be very helpful for locating the code connected with a component; clicking on the component in the browser brings up its code in the editor.

Each component has its properties - these are usually some values which describe the component. Some of them may affect the way component looks, some may change the component's behavior, and some may be dedicated to programming facilities. You will also find that there are some properties -- such as position and size -- common to many components.

wxSmith allows you to edit components inside the properties browser (the window which is usually under the resource browser). If you select a component either by clicking on it in the resource browser or by clicking on it inside the editor, the properties editor switches to edit its properties. Here's an example of the property browser:

Wxs tut02 009.png


You can also use the Quick-Properties panel available after pressing the "Q" button on the right side of the editor:

Wxs tut02 010.png

The purpose of this panel is to provide most common properties in user-friendly way. It hasn't proven as useful as I had hoped, and you will probably find it helpful only while adjusting sizer-related settings.

The last and the easiest way to work on a component is directly in the editor. You can grab drag boxes and change the component's size. You can also change its position by simply dragging it to another place.

Excercise with Components

Enough generalities; let's play with components. We can continue with the project started at the beginning of this tutorial. First let's add wxFlexGridSizer into our window. Like all sizers, it is located in Layout tab. (You'll remember how to add components from the previous tutorial). Now let's add the following components into the sizer in the order given: wxButton, wxStaticText, wxTextCtrl, wxRadioButton and wxCheckBox. They can all be found on the Standard tab. The result should look like this:

Wxs tut02 011.png

In this picture, components I've selected have a light red border.

Now that we have our playground, let's change some components. First, let's change the label and color of the button. To do so, click on the button and move to the properties browser. "Label" is the first property, and it's quite easy to change. Just click on the word "Label" on the right and type new text.

Color is little bit harder to find. Usually components have two colors - Background and Foreground color. Background, as the name implies, is used to fill the component's background. Foreground, on the other hand, is used to paint some content onto the background. Note that there's no strict interpretation of these colors so you should experiment to find out their meaning. In wxButton, Background is what we want. So let's find the Background property. It's value can be changed by using combobox:

Wxs tut02 012.png

On the list you may find a set of predefined system colors. When you choose one of them, they will be read from the current system settings making your application compatible with the system theme. There are also two special entries - Default (which means that we do not want to set our color) and Custom. When you select Custom, wxSmith will open a color dialog where you can choose any color you like. I have chosen light green, and here's the result:

Wxs tut02 013.png

There are also other properties we could talk about, but the best way to learn them is to play with them, so I leave those discoveries to you.

Now let's use the mouse.

The selected component will have eight black boxes -- drag handles -- around it. These boxes can be used to change the size of the component. You will easily notice when the mouse is over a handle because the cursor changes. Let's resize the wxTextCtrl (edit box):

Wxs tut02 014.png

You may see that resizing the component will also change properties in the browser - Default Size is unchecked now and Width and Height are set to required values. There's another property which seems to be untouched - Size in Dialog Units, which is also related to size. I'll explain it a bit.

Usually when you must specify a size (or other size-related things) you provide a value in pixels. Alternatively you can specify values in a unit called a Dialog Unit. A Dialog Unit is usually a little bit bigger than one pixel and it's size depends on the size of the current font (actually it's the size of the font of some component's parent which has a font). This is useful when you want some values to be proportional to the size of text presented in the window.

If you check 'Size in Dialog Units, wxSmith will take care of it and sizes will be calculated in Dialog Units instead of pixels (although, naturally, you will still be able to resize components).

Now let's change the position of the radio box. "But, wait," you may say, "I thought you said that the sizer is responsible for the positioning." That's right. We have limited possibilities to change position. Inside one sizer we can only reorder components; for more complex forms we can also move a component between two sizers or to areas where sizers do not apply. So, back to our example, let's move the radio box to position it right after the button. To do so, click on the radio button and drag it onto the button. When you start dragging, you will notice that the area of the sizer changes color to blue. This color change is an aid to show you what will be the new position of the dragged component. When you move the cursor onto the button, half of the button will become light-blue. When the left half is highlighted, the dragged component will be added before it. When the right half is highlighted, dragged component will be added after it. And when there's no highlighted component, the new component will be added as the last child of the parent:

Wxs tut02 015.png


When you drop the component, it will change it's position. Note that all the components after the new position also shift. That happens because the default setting of the wxFlexGridSizer allows only 3 components in one row (this can be changed in property browser) so the components just adapted to the new order.

Wxs tut02 016.png

Sizers

Now let's learn a little bit about components available in wxSmith. I'll describe all supported sizers and a few important components from the Standard palette. Let's start with sizers.

We already know that sizers are responsible for automatically setting the position and size of some components. But how do they do that? Well, it depends on which sizer has been used. So what are the rules? The generic rule is that the sizer tries to use all its available space and place the components it manages in such way that they do not overlap. If the area available to the sizer is too small, it requests a bigger area, so you can be sure that no component will fall out of the window. (Unfortunately, you cannot be sure that after such adjustments the window will be small enough to fit on the screen, so be careful about 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 a window using sizers, you should be aware that you edit the smallest layout and without some tricks, you won't be able to resize the window to something smaller.

Here are descriptions of all 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 proportions between components - for a horizontal sizer you can set factors which will keep proportionality of widths and the height of the sizer area will be equal to the height of the tallest component. Similarly, vertical sizers keep heights proportional and the width will be taken from the widest component. You specify whether the sizer is to be horizontal or vertical in the sizer's property browser.

Here are examples of layout using box sizers (the first one is the horizontal one, the second is vertical one):

Wxs tut02 002.png


In that example you may see that all components have the same width and height.

But let's assume that we want Button2 to be two times wider that Button1 and Button3 to be three 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 they have equal size. Changing the Proportion of second button to 2 would mean that it should be 2 times wider than the first or third one.

Generally you can set any value you want here. One common technique is to set percentage values - 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 30% and the third one 50%. The special value 0 means that this component should be skipped in proportion calculations and it won't automatically adjust it's size when the main window is resized.

So if we want to get 1:2:3 proportions, we set 1 for Button1, 2 for Button2 and 3 for Button3. And here is the result:

Wxs tut02 003.png

Also note that if you create a resizable window and resize it, those 3 buttons will automatically grow and keep proportions. If you set the Proportion property for some component to 0, it won't change size as the user changes the size of the window.

The other dimension which is not controlled by the "Proportion" property may be controlled using the "Expand" and "Shaped" properties. They are simple checkboxes. If you check the first one, the component will expand it's width/height and will get the size of the biggest component managed by the same sizer. Selecting "Shaped" will also make the component resize but such components will try to keep the initial proportion between width and height so it doesn't have to use all available space. The effect of the "Expand" and "Shaped" properties can be seen when components differ in width or height; here's an example:

Wxs tut02 004.png

In this example, the first button is the biggest of the three. Its size will be used to adjust the sizes of the other buttons. The second one has its "Expand" property checked, and the third one does not. What can be seen here is that the third button expanded in only one dimension (the one managed by "Proportion" property), the second dimension was left untouched.

You may also note that when a component does not fill its available area, it is centered. That's default behavior which can be changed. In the properties of components managed by sizer you will find properties called Horizontal align and Vertical align. Using these properties you can select where the component should be located when it's smaller that its available area.

wxStaticBoxSizer

This sizer is similar to wxBoxSizer with one exception: it adds an extra static box around managed components:

Wxs tut02 005.png

wxGridSizer

This sizer is a little bit more advanced than wxBoxSizer because it aligns components on a grid, not on one line. You can specify the number of columns or number of rows in properties "Cols" and "Rows". The default number of columns is set to 3 and number of rows is set to 0. When 0 is used, it means that sizer should automatically calculate this value to keep all managed components inside.

This sizer makes an important assumption: all cells must have the same width and all must have the same height. This means that the tallest managed component will set the height of all rows and the widest one will set the widths of all columns. If an component won't use the whole cell, it will be surrounded by empty space. (If you don't like this assumption, look at the wxFlexGridSizer.)

Among the properties of a wxGridSizer you can also find horizontal and vertical spacings. These values set the spacing added between components. The result of using them is similar to using borders around managed components but with borders you would have to set borders for all components separately.

In the 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 a grid sizer:

Wxs tut02 006.png

wxFlexGridSizer

This is a very useful one. It works similarly to wxGridSizer; but it does not force all columns to have the same width nor all rows to have the same height. Also not all columns 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 a list of columns / rows which should automatically resize by providing a list of numbers separated using comma (,). The numbers should start from 0, so if you would like the second and third column to resize, put "1,2" into "Growable cols". This property is very useful to handle resizing of the window.

Unfortunately you won't be able to set proportions other that 1:1 The "Proportion" property is also not used in this sizer.

wxStdDialogButtonSizer

This is a specialized sizer with one purpose - to provide a set of standard buttons with respect to the platform's look and feel. This sizer has a predefined list of components which it can handle - all are buttons and you can manage them using the sizer's properties. You cannot add your custom components into this sizer.

Each button on this sizer has two properties in the sizer - whether the button should be enabled (for example wxID_OK for OK button) and its label. Note that labels for most buttons will be generated automatically and wxWidgets will skip them when it can read them from the system settings. For example, on Linux only the Context Help button does not have a system-supplied label. It is also very probable that labels will be provided with language-specific strings (depending on the 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).

Here is an example of this sizer. My system is set up in Polish, so the labels are automatically in Polish. They mean: Help, Cancel, Apply and OK.

Wxs tut02 007.png

This screenshot was taken on a Linux box. You may see that the buttons have an extra image which is not available for standard buttons. With such a layout, users of the application will feel more comfortable, and such 'small' things make users say that the GUI was designed very well. On MS Windows, the sizer would have the same buttons but without images and they would be in a different order - the one that is used on windows by default.

All of the above sizers can be found on the "Layout" tab. You can find two other components there which are not sizers but can be used for layout purposes.

The first one is Spacer. It can be added to other sizers 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 a dividing line (it's called a sash in wxWidgets). On the application you can drag it to dynamically adjust the size of managed components.

Now that we know something about sizers let's turn to other components.

Especially Useful Standard Components

wxWidgets provides all standard graphical components like static text, buttons, edit boxes, combo boxes, and so on. All are supported in wxSmith, so you can build a nice working environment. I'll briefly describe the components that are really useful in standard applications.

wxButton

Wxs tut02 017.png

This is standard button, a very common component. Its purpose is to run some piece of code when the user clicks on it. That's it.

wxStaticText

Wxs tut02 018.png

This component only shows user-defined text on the window. It doesn't generate any events.

wxTextCtrl

Wxs tut02 019.png

This component let's the user enter some text. It's basic functionality allows entering one-line text. After changing its properties, it may become a more advanced multiline editor with support for different fonts, colors and text styles.

wxPanel

Wxs tut02 020.png

Although this component may be a separate window, it is most commonly added as a comoponent in a parent window. It is particularly useful as a background for other components. It has a few functionalities - it can be used as background in notebooks and it may be a place where you put components without sizers. But it also has a few drawbacks - wxWidgets tends to do some tricks with wxPanel's size so it's not always possible to set the size we really want.

wxChoice

Wxs tut02 021.png

This component provides a drop-down list with available options. It works similarly to wxComboBox but the user cannot enter values. It can be used in situations when the user should use one of several available options. An event is generated when the user changes the selected component.

wxComboBox

Wxs tut02 022.png

This component provides a drop-down list similar to that of wxChoice. In the case of this component, the user can select one of the available values or enter his own if the component is not in a Read-Only state. A very good example of its usage is to provide some text entry with a stored list of previously entered values (like in search boxes). Like wxChoice, changing the selection generates an event. Additionally, changing the text and pressing enter also generates events. Tutorial 9 will illustrate its use.

wxListBox

Wxs tut02 023.png

This component provides a list where you can select one or more components. Changing the component or double-clicking on it generates an event.

wxNotebook

Wxs tut02 024.png

Notebook is very useful for complex resources since it groups content under tabs. Additionally, wxChoicebook and wxCombobook are also available but are not described here. Changing the selected notebook generates two events: one when the page starts to change (before change) and one when the page is finished changing (after change).

wxCheckBox

Wxs tut02 025.png

Check boxes may be used to map boolean values. Additionally, 2-state boxes can also be generated (with values: yes/no/unspecified). Changing the value emits an event.

wxRadioBox

Wxs tut02 026.png

Radio box works similarly to check boxes. The difference is that only one radiobox in a group can be selected. Groups may be defined by using wxRB_GROUP style. A radiobox which has this style set starts a new group. Changing the selected radiobox emits an event.

wxGauge

Wxs tut02 027.png

This component, also called a Progress Bar, can be used to show the progress of some operation. It's very useful when doing some calculation intensive operations. It can prevent users from getting frustrated when they do not see anything happening on the screen but only a window which seems hung.

* * * *

That's the end of this tutorial. We will get more experience with these subjects in the following tutorials. But you can also learn a lot by experimenting: add components, change properties, resize, move. You may try adding sizers into other sizers, a very useful technique absolutely required for more complex forms. Join me for the next tutorial!


Previous | Index | Next