wxWidgets Examples

Starting off with a GUI library can be quite daunting. Lots of new code and classes need to be written to get even the most basic program working. I have found that the best way to get started with wxWidgets is to look at its examples. Pick the example that implements most of what you need and start off from there.

Doing this is easy:

  • Install the wxWidgets examples:
$ sudo apt-get install wx3.0-examples
  • The examples are zipped up and need to be uncompressed before using them:
$ cd /usr/share/doc/wx3.0-examples/examples
$ ./unpack_examples.sh ~/wx-examples
  • You can build all the examples in one command:
$ cd ~/wx-examples/samples
$ make
  • Or you can go to a specific directory and build a specific example:
$ cd ~/wx-examples/samples/opengl/penguin
$ make

Tried with: wxWidgets 3.0 and Ubuntu 14.04

How to get mouse position in wxWidgets

To get mouse position relative to top-left corner of display, add this in a mouse event handler:

const wxPoint pt = wxGetMousePosition();
int mouseX = pt.x;
int mouseY = pt.y;

To get mouse position relative to top-left corner of current window or canvas, add this in a mouse event handler:

const wxPoint pt = wxGetMousePosition();
int mouseX = pt.x - this->GetScreenPosition().x;
int mouseY = pt.y - this->GetScreenPosition().y;

Tried with: wxWidgets 3.0 and Ubuntu 14.04

Segmentation fault at glCreateShader in wxWidgets

Problem

I had a simple graphics program written using OpenGL and using GLUT for windowing. To get more windowing functionality, I wanted to move it to wxWidgets. I picked an example program that uses OpenGL in wxWidgets. It compiled and worked correctly. When I placed my OpenGL code into this example, I got a segmentation fault at the glCreateShader call in my code.

Solution

I had a glewInit in my original code. I had put this in the application class constructor. Apparently, wxWidgets requires that the first OpenGL or GLEW call be placed inside the OnPaint event handler function. Look for EVT_PAINT to find this function. Once I did that, the error disappeared and OpenGL worked.

How to build wxWidgets program using CMake

Configuring a project that uses wxWidgets to build on Windows is quite simple. However, on Linux the same task is a bit more involved and requires using the wx-config program.

CMake has support for wxWidgets, but requires knowing the right incantations to build. A minimal CMakeLists.txt for building a wxWidgets program is given below:

This includes the core and base wxWidgets libraries. If you use any other wxWidgets modules, like wxGLCanvas for example, then include the relevant modules, like gl in the find_package command.

Tried with: wxWidgets 3.0, CMake 2.8.12.2 and Ubuntu 14.04

How to display an array as image in wxWidgets

There are many scenarios where you get an array of values that represents an image of certain width and height. For example, the array could contain integers or floats of any range. You might want to display this array in wxWidgets to visualize it as a two-dimensional image.

Here is one way I was able to do this in wxWidgets:

  • A common type of value that wxWidgets uses for display is unsigned char. This has a range of 0 to 255. So, you will need to convert your float, int or any other type to unsigned char. How you do this conversion will depend on the range of values that are being represented in your type.

  • The typical type of array that wxWidgets uses for display is 3-channel (RGB) or 4-channel (RGBA). So, if you have one or two channel arrays, you will need to convert them to a 3-channel array. The values are arranged such that the RGB values of a pixel are adjacent to each other. That is, the array should be arranged as [R0 G0 B0 R1 G1 B1 ...]. If you have a single channel array, the easiest way to generate 3-channel array is to allocate a new array of 3 times the size and write every value thrice into it. Remember that the values in the array should be of type unsigned char as explained earlier.

  • One of the structures that is used to hold an image is wxImage. You can initialize it with a 3-channel array of type unsigned char as follows:

unsigned char* imgArray[width * height * 3];
// Fill in imgArray here ... 
wxImage img(width, height, imgArray, true);
  • The easiest structure to use to draw on the GUI is wxBitmap. You can directly convert a wxImage to it:
wxBitmap bmp(img);
  • Finally, we are ready to draw on the GUI. The widget that can be used to draw is wxStaticBitmap. Pass it a wxBitmap and it will render it on the GUI:
// Start with empty bitmap
wxStaticBitmap* sbmp = new wxStaticBitmap(this, wxID_STATIC, wxNullBitmap, wxDefaultPosition, wxSize(width, height));
// Update later with your bitmap
sbmp->SetBitmap(bmp);

Tried with: wxWidgets 3.0.0 and Visual Studio 2012

How to get started with wxWidgets on Windows

wxWidgets is a cross-platform GUI library, that is also available for Windows. You can get started with using wxWidgets in a few steps:

  1. Download and install the Windows installer for the current stable release of wxWidgets from its download page. It installs the source and build files in C:. For example, in C:\wxWidgets-3.0.0\

  2. wxWidgets needs to be built before it can be used with your application. Go to C:\wxWidgets-3.0.0\build\msw and open the .sln file that matches the Visual Studio version you intend to use for your application. For example, I open wx_vc10.sln using Visual Studio 2010.

  3. Choose one of the build types: Debug, Release, DLL Debug or DLL Release and build the solution. The resulting .lib files are placed in C:\wxWidgets-3.0.0\lib\vc_lib

  4. Create a new Visual Studio solution for your C++ application. Remember that it has to be Win32 Project, not a Win32 Console Project. The difference is that the main function is defined inside wxWidgets and does not need to be defined in your application code.

  5. Add a .cpp file to your solution and copy the Hello World code into it.

  6. Add C:\wxWidgets-3.0.0\include and C:\wxWidgets-3.0.0\include\msvc as additional include directories to the solution.

  7. Add C:\wxWidgets-3.0.0\lib\vc_lib as additional library directory to the solution.

  8. Build the solution and run it to see an empty wxWidgets window.

Tried with: wxWidgets 3.0.0, Visual Studio 2012 and Windows 7 x64

Unicode wxWidgets in a Non-Unicode World

wxWidgets can be compiled to pure Unicode mode by setting wxUSE_UNICODE to 1 in the header file $(WX_WIDGETS_ROOT)\include\wx\msw\setup.h

But what if the rest of your code that interfaces with Unicode wxWidgets is still not Unicode, but uses char and STL std::string? The changes needed at the interface are:

  • Wrap all characters and string literals passed to wxWidgets in wxT(). It converts them to Unicode. Ex: wxT("Hell World!")
  • wxWidget functions do not deal with STL std::string but with wxString. Do the conversion using wxConvUTF8, which is an instance of the wxMBConv class. MBConv stands for Multi-Byte Conversion, it helps to convert between Multi-Byte formats and Unicode. wxConvUTF8 as you can guess converts multi-byte to the UTF-8 Unicode encoding.
    Ex:

    std::string stdStr("Hell World!");
    wxString wxStr(stdStr.c_str(), wxConvUTF8);
  • When wxWidgets functions throw out a wxString, convert them back to char string using wxString::mb_str(). This returns the multi-byte representation of the internal Unicode text in wxString.

If you are curious about this fishy Multi-Byte business, check out Windows: Multi-Byte.