Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

b4swine's scratchpad

by b4swine (Pilgrim)
on Oct 10, 2006 at 04:35 UTC ( #577324=scratchpad: print w/replies, xml ) Need Help??

WxSimple Tutorial

This is a tutorial for WxSimple, a package I wrote to make throwaway WxPerl programs using XRC.

GUI programming always looks rather bulky. This package makes the code much smaller, making it easy to write throwaway, one-time programs. This package is very useful for the absolute beginner as well as for experienced WxPerlers.

For beginners, the advantage of using XRC, is that you can use a GUI to create you menus, toolbar, and your buttons windows, panels, etc, along with sizers, and can test them live. This frees you up to concentrate on programming. Later on, when dynamic objects are needed, you can learn the internals of sizers and creation/deletion of windows at your own pace.

Getting Started

To get started, you need to get some components together, becuase unfortuantely, Wx is not a standard package.

Since I use ActivePerl for MS Windows, I have provided complete instructions for that. For *nix users it should be easier. Use ppm to download the Wx package. Unfortunately, most repositories have very ancient binaries for WxPerl, so to get the latest version, you will need to add the repositories described in

You also need to get some kind of a XML resource compiler. I like XRCed (because it is the only one I have used), but it requires you to install Python as well. You need to download and install python (about 10 megs) from, and then download and install WxPython (about 5 megs) from

You are now ready to use the XRCed program included with WxPython. If you open the file WxSample.xrc (file located at the end), in XRCed, you can explore how this is structured.

Sample Program: For those than know WxPerl

For those who are already familiar with WxPerl, a sample program illustrating the use of WxSimple is provided here. It will need two other supporting files namely the package and the resource file WxSample.xrc that was created using XRCed. Both of these files are given in the last section.

Here is the code for

use strict; use warnings; use WxSimple qw(FindWindowByXid MsgBox $xrc $sbar $OpenFile $frame); # # set up parameters # $xrc = 'WxSample.xrc'; # location of xrc file $sbar = 2; # status bar with 2 sections $OpenFile = \&OpenFile; # funtion that opens a file # # create an app # my $app = WxSimple->new(); # create app and main frame # # now, find controls inside the main window # and set up event handlers for them. # my ($checkbox, $id) = FindWindowByXid('CheckBox'); Wx::Event::EVT_CHECKBOX($frame, $id, \&OnCheck ); my $smalltext = FindWindowByXid('SmallText'); # # start the main loop # $app->MainLoop(); # # ------------------------------------- # here are the event handlers # run the program. Open a file. Check the checkbox # sub OpenFile { my $file = shift; local $/; my $textbox = FindWindowByXid('Text'); open F, '<', $file; $textbox->ChangeValue(<F>); close F; MsgBox('The file is loaded in the text box'); } sub OnCheck { my ($this, $evt) = @_; if ($evt->IsChecked()) { $smalltext->ChangeValue('checked'); } else { $smalltext->ChangeValue('unchecked'); } }

A Typical Sequence

We go through a typical sequence needed to create a program using WxSimple.

1. Use XRCed to create Menu and a Window Layout

First a resource file is created using XRCed. In this , there is a main frame, and inside the frame you may have a menu and possibly a toolbar as well. You can also put any other containers, buttons, sliders, etc. as you like. Each object needs an XMLid, which is just a name, if you are going to be referring to it in the Perl program. For example, you usually do not need to give an ID for StaticText, because there is no need to refer to it. Finally save this as an xrc file. There are a set of default XMLid's for many of the standard menu items (you can find them in the index under "Window Identifiers"). there is an advantage in using the standard names although you can .

2. Set Parameters

A typical programs first sets up parameters. This is done by
use WxSimple qw($xrc $frmID $sbar %menu $OpenFile $SaveFile $Close +Win $icon);

$xrc refers to the path to the file that was created by XRCed.

$frmID is the XMLid that was given to the main frame created in the xrc file.

$sbar is the number of panels in the status bar at the bottom of the window. If this is zero, no status bar is created.

%menu is a hash with the XMLids of the menu items as keys, and coderefs to subs that will be called as values. Four items in this hash are predefined, but may be overwritten. File--Open, File--Save, File--SaveAs, have predefined handlers which offer a file dialog and get a file name, after which the call the code referenced by &$OpenFile or &$SaveFile, as appropriate. You should make an entry for every one of the menu items that you want to be active. You can override the predefined items as well, by redefining them.

$OpenFile and $SaveFile are described above in %menu.

&$CloseWin is the routine called when the window is closed. It should Destroy all top level windows. If you create other top level windows, you should redefine this.

$icon is a default WxPerl icon, which you can change as you like.

3. Create an App

Creating a WxSimple app by my $app = WxSimple->new() .

4. Add more Handlers

After that, the variables $WxSimple::frame and $WxSimple::xr get set to the top-level frame and the XML resource, respectively. Any other item within the frame can be located using its XML id, with
my ($window, $id) = WxSimple::FindWindowByXid('xmlid')
The $id is a numeric ID that is associated with that control or window. It is needed if you want to respond to other events from that control.

5. Define Handler Routines

If you are going to be using files, you need to define $WxSimple::FileOpen, or $WxSimple::FileSave, as appropriate. Initially these are set to dummy routines, but you can refer them to your own routine, as illustrated above for FileOpen.

You may now define routines for each of the menu items, as well as other event handlers you have defined.

For those learning WxPerl

This module is actually a useful way to learn WxPerl, even for a beginner. You can get a very fast start, and then learn the hard way of doing things at your own pace. It is useful to be aware of the resources available to learn WxPerl.


A manual intended for C programmers, with one-line notes for Perl and Python is available. This is not up to date, but this is all there is.


There are a nice set of tutorials here.


Along with WxPerl, two kinds of sample programs are provided. One is a very large sample program called which illustrates many of the various controls, in one integrated program. The other is directory samples which contains a set of small independent programs, each of which illustrates one control.


A wiki devoted to wxperl, is a bit undermaintained, and out of date, but you can find many things here.


Supporting Code

In order to run, this needs two additional support files, and WxSample.xrc. The first is the package, while the second is an xml file that was created (and should be edited) using XRCed. The files are provided below. If you put all three in a single directory, you can run
package WxSimple; use base qw(Wx::App Exporter); use strict; use Exporter; our $VERSION = 0.10; our @EXPORT_OK = qw(StartApp FindWindowByXid MsgBox $frame $xr $xrc $frmID $sbar %menu $OpenFile $SaveFile $CloseWin $icon); use Wx; use Carp; our $frame; our $xr; our $xrc = 'res/res.xrc'; # location of resource file our $frmID = 'Frame'; # XML ID of the main frame our $sbar = 0; # number of status bar sections our %menu = # menu handlers, # you can replace them with your own # or add your own menu items ( wxID_OPEN => \&Open, # these are four readymade handl +ers wxID_SAVE => \&Save, # that just get a file-name for r +eading wxID_SAVEAS => \&SaveAs,# or writing wxID_EXIT => \&Exit, # and quit just exits. ); our $OpenFile = \&OpenFile; # A routine to read data from a file our $SaveFile = \&SaveFile; # A routine to write data to a file our $CloseWin = \&CloseWin; # this is not a menu option # it is the routine called before the end # it needs to Destroy() all top level dialogs our $icon = Wx::GetWxPerlIcon(); my $file; # the name of the file used in Open/Save sub StartApp { WxSimple->new()->MainLoop(); } sub OnInit { my $app = shift; # # Load XML Resources # use Wx::XRC; $xr = Wx::XmlResource->new(); $xr->InitAllHandlers(); croak "No Resource file $xrc" unless -e $xrc; $xr->Load( $xrc ); # # Load the main frame from resources # $frame = 'Wx::Frame'->new; croak "No Frame named $frmID in $xrc" unless $xr->LoadFrame($frame, undef, $frmID); if ($sbar) { $frame->CreateStatusBar( $sbar ); $frame->SetStatusWidths(-1,200); } $frame->SetIcon( $icon ); # # Set event handlers # use Wx::Event qw(EVT_MENU EVT_CLOSE); while (my ($xrcid, $handler) = each %menu) { my $id = Wx::XmlResource::GetXRCID($xrcid, -2); if ($id == -2) { carp "No MenuItem named $xrcid"; next; } EVT_MENU( $frame, $id, $handler ); } EVT_CLOSE( $frame, $CloseWin ); # # Show the window # $app->SetTopWindow( $frame ); $frame -> Show(1); 1; } sub FindWindowByXid { my $id = Wx::XmlResource::GetXRCID($_[0], -2); return undef if $id == -2; my $win = Wx::Window::FindWindowById($id, $frame); return wantarray ? ($win, $id) : $win; } sub MsgBox { use Wx qw (wxOK wxICON_EXCLAMATION); my @args = @_; $args[1] = 'Message' unless defined $args[1]; $args[2] = wxOK | wxICON_EXCLAMATION unless defined $args[2]; my $md = Wx::MessageDialog->new($frame, @args); $md->ShowModal(); } sub Open { use Wx qw (wxID_CANCEL wxFD_FILE_MUST_EXIST); my $dlg = Wx::FileDialog->new($frame, 'Select one or more Files', '', '', 'Text Files|*.txt|All Files|*.*', wxFD_FILE_MUST_EXIST); if ($dlg->ShowModal() == wxID_CANCEL) { return } $file = $dlg->GetPath(); $frame->SetStatusText("Opening...$file", 0); my $busy = Wx::BusyCursor->new(); $OpenFile->($file); $frame->SetStatusText("Opening...$file...Done", 0); } sub Save { $frame->SetStatusText("Saving...$file", 0); my $busy = Wx::BusyCursor->new(); $SaveFile->($file); $frame->SetStatusText("Saving...$file...Done", 0); } sub SaveAs { use Wx qw (wxID_CANCEL wxFD_OVERWRITE_PROMPT wxFD_SAVE); my $dlg = Wx::FileDialog->new($frame, 'Select one or more Files', '', '', 'Text Files|*.txt|All Files|*.*', wxFD_OVERWRITE_PROMPT | wxFD_SAVE); if ($dlg->ShowModal() == wxID_CANCEL) { return } $file = $dlg->GetPath(); Save(); } sub OpenFile { MsgBox "Add Code to Open $file"; } sub SaveFile { MsgBox "Add Code to Save $file"; } sub Exit { CloseWin(); } # # Close is not called by the menu, but is called to close all wind +ows # If there are any toplevel dialogs, close them here, otherwise th +e # program will not exit. # sub CloseWin { $frame->Destroy(); } 1; __END__ =head1 NAME WxSimple: A package to make throwaway WxPerl programs using C<XRC> =head1 SYNOPSIS use WxSimple; # one-liner (use all default options) WxSimple::StartApp(); ... # with modified defaults use WxSimple qw(qw(StartApp FindWindowByXid MsgBox $frame $xr $xrc $frmID $sbar %menu $OpenFile $SaveFile $CloseWin $icon); $xrc = 'res/res.xrc'; $frmID = 'MainFrame'; $sbar = 1; $menu{OpenFile} = \&::Open; $menu{Options} = \&::OnOptions; ... my $app = WxSimple->new(); ... $app->MainLoop(); =head1 DESCRIPTION GUI programming always looks rather bulky. This package makes the code much smaller, making it easy to write throwaway, one-time use WxPerl programs. The windows, menus, toolbars are all defined usin +g C<XRC>. To simplify menu event handling, just define the hash C<%WxSimple: +:menu> with keys that are the XML ID's for each menuitem, and values that + are references to the handlers for that menuitem. The menu events for C<wxID_OPEN>, C<wxID_SAVE>, C<wxID_SAVEAS> and + C<wxID_EXIT> have default definitions. The first three events get +a file name (using a file dialog for Open and Save As) and then call + the coderef pointed to by $FileOpen, or $FileSave, with that file +name as the argument. Quit will close the window and exit. You can over +ride any of these definitions, by redefining C<%WxSimple::menu>. The XML ID for the main frame is given in C<$WxSimple::frmID>. The number of sections in the status bar is given by C<$WxSimple:: +sbar>. If this is C<0>, no status bar is created. The name of the XML resource file generated by XRC is set in C<$WxSimple::xrc>. The variables C<$WxSimple::frame> and C<$WxSimple::xr> contain the + main frame and the XML resource, once C<new> has been called =head2 Structure The main program usually looks like a C<use WxSimple> statement, f +ollowed by setting a few parameters. Then the C<%WxSimple::menu> hash usua +lly has to be defined, providing a handler for every menu event. This is followed by creating a C<$app> using a call to C<WxSimple- +>new()>. At this point the variables C<$WxSimple::frame> and C<$WxSimple::x +r> are created. If further things need to be added to the frame, this is +the time to do that. Finally a call to C<MainLoop()> starts the window loop.
<?xml version="1.0" ?> <resource> <object class="wxFrame" name="Frame"> <title>DataProg</title> <object class="wxToolBar" name="XRCtbar"> <bitmapsize>32</bitmapsize> <size>32,32</size> <readmore> <object class="tool" name="wxID_NEW"> <bitmap stock_id="wxART_NEW"></bitmap> <tooltip>New</tooltip> <longhelp>Start a new file</longhelp> </object> <object class="tool" name="wxID_OPEN"> <bitmap stock_id="wxART_FILE_OPEN"></bitmap> <tooltip>Open</tooltip> <longhelp>Open a File</longhelp> </object> <object class="tool" name="wxID_SAVE"> <bitmap stock_id="wxART_FILE_SAVE"></bitmap> <tooltip>Save currently opened File</tooltip> <longhelp></longhelp> </object> <object class="tool" name="wxID_SAVEAS"> <bitmap stock_id="wxART_FILE_SAVE_AS"></bitmap> <tooltip>Save File under a different name</tooltip> </object> <object class="tool" name="wxID_EXIT"> <bitmap stock_id="wxART_QUIT"></bitmap> <tooltip>Exit Program</tooltip> <longhelp>Exit Program</longhelp> </object> <object class="separator"/> <object class="tool" name="wxID_CUT"> <bitmap stock_id="wxART_CUT"></bitmap> </object> <object class="tool" name="wxID_COPY"> <bitmap stock_id="wxART_COPY"></bitmap> </object> <object class="tool" name="wxID_PASTE"> <bitmap stock_id="wxART_PASTE"></bitmap> </object> <object class="tool" name="wxID_DELETE"> <bitmap stock_id="wxART_DELETE"></bitmap> </object> <object class="separator"/> <object class="tool" name="wxID_HELP"> <bitmap stock_id="wxART_HELP"></bitmap> <tooltip>Help</tooltip> <longhelp>Usage Instructions</longhelp> </object> <object class="tool" name="wxID_ABOUT"> <bitmap stock_id="wxART_INFORMATION"></bitmap> <tooltip>About</tooltip> <longhelp>Information about this program</longhelp> </object> </object> <object class="wxMenuBar" name="XRCmenu"> <object class="wxMenu" name="menuFile"> <label>File</label> <object class="wxMenuItem" name="wxID_NEW"> <label>New</label> <bitmap stock_id="wxART_NEW"></bitmap> <accel>Ctrl-N</accel> <help>Start a new file</help> </object> <object class="wxMenuItem" name="wxID_OPEN"> <label>Open</label> <bitmap stock_id="wxART_FILE_OPEN"></bitmap> <accel>Ctrl-O</accel> <help>Open a File</help> </object> <object class="wxMenuItem" name="wxID_REVERT"> <label>Revert to Saved</label> </object> <object class="wxMenuItem" name="wxID_SAVE"> <label>Save</label> <bitmap stock_id="wxART_FILE_SAVE"></bitmap> <accel>ctrl-S</accel> <help>Save currently opened File</help> </object> <object class="wxMenuItem" name="wxID_SAVEAS"> <label>Save As</label> <bitmap stock_id="wxART_FILE_SAVE"></bitmap> <accel>ctrl-S</accel> <help>Save File under a different name</help> </object> <object class="wxMenuItem" name="wxID_EXIT"> <label>Exit</label> <bitmap stock_id="wxART_QUIT"></bitmap> <accel>Ctrl-X</accel> <help>Exit Program</help> </object> </object> <object class="wxMenu" name="menuEdit"> <label>Edit</label> <object class="wxMenuItem" name="wxID_CUT"> <label>Cut</label> <bitmap stock_id="wxART_CUT"></bitmap> </object> <object class="wxMenuItem" name="wxID_COPY"> <label>Copy</label> <bitmap stock_id="wxART_COPY"></bitmap> </object> <object class="wxMenuItem" name="wxID_PASTE"> <label>Paste</label> <bitmap stock_id="wxART_PASTE"></bitmap> </object> <object class="wxMenuItem" name="wxID_DELETE"> <label>Delete</label> <bitmap stock_id="wxART_DELETE"></bitmap> </object> </object> <object class="wxMenu" name="menuHelp"> <label>Help</label> <object class="wxMenuItem" name="wxID_HELP"> <label>Help</label> <bitmap stock_id="wxART_HELP"></bitmap> <accel>F1</accel> <help>Usage instructions</help> </object> <object class="wxMenuItem" name="wxID_ABOUT"> <label>About</label> <bitmap stock_id="wxART_INFORMATION"></bitmap> <help>Information about this program</help> </object> </object> </object> <object class="wxSplitterWindow"> <object class="wxTextCtrl" name="Text"> <style>wxTE_MULTILINE</style> </object> <object class="wxPanel"> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxCheckBox" name="CheckBox"> <label>A little checkbox</label> </object> </object> <object class="sizeritem"> <object class="wxTextCtrl" name="SmallText"/> </object> </object> </object> <orientation>vertical</orientation> <sashpos>100</sashpos> </object> <style></style> </object> </resource> </readmore>
Log In?

What's my password?
Create A New User
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (9)
As of 2018-06-18 19:40 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (110 votes). Check out past polls.