Difference between revisions of "WxSmith tutorial: Accessing items in resource"

From Code::Blocks
m (Minor edits for clarity)
m (Minor edits for clarity)
Line 49: Line 49:
 
If the name is invalid, wxSmith will automatically replace it with a name that matches the criteria.
 
If the name is invalid, wxSmith will automatically replace it with a name that matches the criteria.
  
= Changing label in wxStaticText =
+
= Changing the label in wxStaticText =
  
Ok, let's do some basic excercise by changing label of first wxStaticText. To do this double click on button next to it to generate event handler and change the code to following thing:
+
Ok, let's do some basic exercise by changing the label of the first wxStaticText. To do this double click on the button next to it to generate an event handler and change the code to the following:
  
  
Line 60: Line 60:
 
  }
 
  }
  
In first line of function body we used '''SetLabel()''' function to change text of label. Because length of the text changes, we must recalculate positions which is done by calling '''Layout()''' function.
+
In the first line of the function body we used the '''SetLabel()''' function to change the text of the label. Because the length of the text changes, we must recalculate positions, which is done by calling the '''Layout()''' function.
  
In case of static items (those which can't be changed by user) usually have two functions: GetLabel and SetLabel which read and write content presented by this item.
+
Static items (those which can't be changed by the user) usually have two functions: GetLabel and SetLabel which read and write content presented by this item.
  
  
You may wonder why we used some weird notation for string:
+
You may wonder why we used some weird notation for the string:
 
  _("Label changed")
 
  _("Label changed")
instead of simple
+
instead of a simple
 
  "Label changed"
 
  "Label changed"
  
There are two advantages of such approach:
+
There are two advantages to such an approach:
* By adding _(...) around our string we prepare our application for translation process. wxWidgets can help developing multilanguage applications and when some some different language will be used, it will automatically search for translaction of "Label changed" text in strings database.
+
* By adding _(...) around our string we prepare our application for the translation process. wxWidgets can help developing multilanguage applications and when some some different language will be used, it will automatically search for the translation of the "Label changed" text in a strings database.
* wxWidgets may be provided in two versions: with unicode support and without it (ansi build). In case of unicode version, we would have to use unicode strings: '''L"Label changed"''' and in case of ansi version we would have to use standard string notation: '''"Label changed"'''. Using '''_(...)''' macro grants that no matter what wxWidgets version is used, it will always produce proper code.
+
* wxWidgets may be provided in two versions: with unicode support and without it (ansi build). In the case of a unicode version, we would have to use unicode strings: '''L"Label changed"''' and in case of ansi version we would have to use standard string notation: '''"Label changed"'''. Using the '''_(...)''' macro grants that no matter what wxWidgets version is used, it will always produce the proper code.
  
There's alternative version of string macro which works simillarily to _(...) which is written in form _T(...) or wxT(...). It works like _() one but the string is never translated.
+
There's an alternative version of the string macro which works similarly to _(...) which is written in the form _T(...) or wxT(...). It works like the _() one but the string is never translated.
  
 
= Reading value from wxTextCtrl =
 
= Reading value from wxTextCtrl =

Revision as of 16:50, 3 December 2010


Accessing items in a resource

Welcome to the next tutorial. This time I'll show you how to access items in a resource. I'll show you some basics - for example how to read data from text boxes, change labels, and some more advanced things like changing colours and fonts while the application is running. As usual we will start with an empty application. You shouldn't have any problems with it - all instructions are in the first tutorial.

Adding a few items we will work on

In this tutorial we will work on items so let's add some:

Wxs tut06 001.png

In this resource wxFlexGridSizer with 2 columns is used as background. In the first three rows we have wxStaticText, wxTextCtrl and wxGauge - we will operate on them using buttons in the right column. Below there is wxSlider which will be used to change the size of the font - I've changed its Max property to 30 to limit the size range. Below there's a button which will be used to change the colours of some items.

Accessing items through members of the resource class

If you add an item in the editor, in most cases wxSmith will add a new member variable into the resource's c++ class. All those members are listed inside //(*Declarations ... //*) code blocks. In the case of the window we created it should look like this:

...
class Tutorial_6Frame: public wxFrame
{
    ...

        //(*Declarations(Tutorial_6Frame)
        wxSlider* Slider1;
        wxButton* Button4;
        wxStaticText* StaticText2;
        wxButton* Button1;
        wxGauge* Gauge1;
        wxStaticText* StaticText1;
        wxStaticText* StaticText3;
        wxButton* Button2;
        wxButton* Button3;
        wxStatusBar* StatusBar1;
        wxTextCtrl* TextCtrl1;
        //*)
    ...
};
...

Each item which has such a member variable will also have the following properties:

  • Var name - name of the used variable
  • Is member - switch whether this item should be accessible through a class member variable

So if you want to change the name used to access the item, Var name is the right property to change.

wxSmith forces a few restrictions on variable names. The most obvious is that each variable name must be a valid c++ identifier so you cannot provide special characters or even spaces. Another limitations is that variable names must be unique. If the name is invalid, wxSmith will automatically replace it with a name that matches the criteria.

Changing the label in wxStaticText

Ok, let's do some basic exercise by changing the label of the first wxStaticText. To do this double click on the button next to it to generate an event handler and change the code to the following:


void Tutorial_6Frame::OnButton1Click(wxCommandEvent& event)
{
    StaticText1->SetLabel(_("Label changed"));
    Layout();
}

In the first line of the function body we used the SetLabel() function to change the text of the label. Because the length of the text changes, we must recalculate positions, which is done by calling the Layout() function.

Static items (those which can't be changed by the user) usually have two functions: GetLabel and SetLabel which read and write content presented by this item.


You may wonder why we used some weird notation for the string:

_("Label changed")

instead of a simple

"Label changed"

There are two advantages to such an approach:

  • By adding _(...) around our string we prepare our application for the translation process. wxWidgets can help developing multilanguage applications and when some some different language will be used, it will automatically search for the translation of the "Label changed" text in a strings database.
  • wxWidgets may be provided in two versions: with unicode support and without it (ansi build). In the case of a unicode version, we would have to use unicode strings: L"Label changed" and in case of ansi version we would have to use standard string notation: "Label changed". Using the _(...) macro grants that no matter what wxWidgets version is used, it will always produce the proper code.

There's an alternative version of the string macro which works similarly to _(...) which is written in the form _T(...) or wxT(...). It works like the _() one but the string is never translated.

Reading value from wxTextCtrl

Now let's read something that's written by user. We will use wxTextCtrl (with variable TextCtrl1) for this and show the text using standard message box. Let's double click the Read text button and change the code to following:

void Tutorial_6Frame::OnButton2Click(wxCommandEvent& event)
{
    wxString Text = TextCtrl1->GetValue();
    wxMessageBox(_("User entered text:\n") + Text);
}

In the first line we read value from TextCtrl and store it inside variable of type wxString. wxString is wxWidgets implementation of string object and this library uses it as base for string representation.

In the second line we call wxMessageBox function which shows standard message box just like it was modal dialog.

Usually items which provide content entered by user have two member functions: GetValue and SetValue. You can use them to read and write content of such item.

Changing value of wxGauge

Now let's mix reading and writing of item's value on one function. We will use wxGauge for this. We will use it's two member functions: GetValue and SetValue. I've written ealier that those functions usually exist in items where user can enter some value. Well it's not a gold rule and there are exceptions from it like in case of this item :).

Ok, let's add handler for third button:

void Tutorial_6Frame::OnButton3Click(wxCommandEvent& event)
{
    int NewValue = Gauge1->GetValue()+10;
    if ( NewValue > 100 ) NewValue = 0;
    Gauge1->SetValue(NewValue);
}

In first line we generate new value of progress by reading current one and adding 10 to it. In second line we prevent the value from getting out of range (by default wxGauge has range set to 0..100 - this can be changed in properties). In third line we write new value into gauge.

Using value from wxSlider to change font size

Now let's do something more advanced. In our resource there's wxSlider and text saying that it changes font size. We will change font of this label. But we will have to update font size in two steps:

  • As long as user draggs the slider we should change font size only
  • When user finishes dragging we should layout window because size of text changes

wxSlider provides two events that can be used right for this purpose. First is EVT_COMMAND_SCROLL_THUMB_TRACK which is fired while dragging the slider. Second is EVT_COMMAND_SCROLL_THUMB_RELEASE which is fired when user finishes dragging.

Because we use events which are not default we would have to add them through properties browser. You can switch between editing standard properties and events by clicking on buttons at the top of browser:

Wxs tut06 002.png.

If you switch to events, search for required events and choose Add new handler from drop-down list. Here's the code for EVT_COMMAND_SCROLL_THUMB_TRACK handler:

void Tutorial_6Frame::OnSlider1CmdScrollThumbTrack(wxScrollEvent& event)
{
    wxFont Font = StaticText2->GetFont();
    Font.SetPointSize( Slider1->GetValue() );
    StaticText2->SetFont(Font);
}

Here we get font used by StaticText control by using GetFont() function, change font's size by using GetPointSize() and write font back by using SetFont() function. GetFont() and SetFont() are available in most items.

Now let's code EVT_COMMAND_SCROLL_THUMB_RELEASE:


void Tutorial_6Frame::OnSlider1CmdScrollThumbRelease(wxScrollEvent& event)
{
    Layout();
    GetSizer()->SetSizeHints(this);
}

In the first line we adopt positions of items to new environment just like in case of changing label in wxStaticText. In the second line we recalculate minimal size of the window making sure that all items will have enough space.

Changing item's colour

Last thing we will do in this tutorial is to change colour of some item. As in case of fonts we will change label on the left side of Change button. Since we will use standard event of this button, we can add event handler by double-clicking on it. And here's the code:

void Tutorial_6Frame::OnButton4Click(wxCommandEvent& event)
{
    wxColour OldColour = StaticText3->GetForegroundColour();
    wxColour NewColour = wxGetColourFromUser(this,OldColour);

    if ( NewColour.IsOk() )
    {
        StaticText3->SetForegroundColour(NewColour);
    }
}

At the beginning we read current colour to variable OldColour. In next lie we call wxGetColourFromUser function which opens dialog where we can choose colour.

The NewColour.IsOk() call is required because if user cancels colour selection it will return false.

At the end we set new colour by using SetForegroundColour function.

Header file to include in the tut....main.h file: #include <wx/colordlg.h>

More informations

We reached end of this tutorial. I showed only few operations on items and there's much more you can do. For more details you can check wxWidgets' documentation available here.