Wednesday, April 5, 2017

wxPython - Quick Guide

wxPython - Introduction

wxPython is a Python wrapper for wxWidgets (which is written in C++), a popular cross-platform GUI toolkit. Developed by Robin Dunn along with Harri Pasanen, wxPython is implemented as a Python extension module.
Just like wxWidgets, wxPython is also a free software. It can be downloaded from the official website http://wxpython.org. Binaries and source code for many operating system platforms are available for download on this site.

Principal modules in wxPython API include a core module. It consists of wxObject class, which is the base for all classes in the API. Control module contains all the widgets used in GUI application development. For example, wx.Button, wx.StaticText (analogous to a label), wx.TextCtrl (editable text control), etc.
wxPython API has GDI (Graphics Device Interface) module. It is a set of classes used for drawing on widgets. Classes like font, color, brush, etc. are a part of it. All the container window classes are defined in Windows module.
Official website of wxPython also hosts Project Phoenix – a new implementation of wxPython for Python 3.*. It focuses on improving speed, maintainability, and extensibility. The project began in 2012 and is still in beta stage.

wxPython - Environment

Windows

Prebuilt binaries for Windows OS (both 32 bit and 64 bit) are available on http://www.wxpython.org/download.php page. Latest versions of installers available are − wxPython3.0-win32-3.0.2.0-py27.exe for 32-bit Python 2.7 wxPython3.0-win64-3.0.2.0-py27.exe for 64-bit Python 2.7
wxPython demo, samples and wxWidgets documentation is also available for download on the same page.
wxPython3.0-win32-docs-demos.exe

Linux

wxPython binaries for many Linux distros can be found in their respective repositories. Corresponding package managers will have to be used to download and install. For instance on Debian Linux, following command should be able to install wxPython.
sudo apt-get install python-wxgtk3.0

MacOS

Prebuilt binaries for MacOS in the form of disk images are available on the download page of the official website.

wxPython - Hello World

A simple GUI application displaying Hello World message is built using the following steps −
  • Import wx module.
  • Define an object of Application class.
  • Create a top level window as object of wx.Frame class. Caption and size parameters are given in constructor.
  • Although other controls can be added in Frame object, their layout cannot be managed. Hence, put a Panel object into the Frame.
  • Add a StaticText object to display ‘Hello World’ at a desired position inside the window.
  • Activate the frame window by show() method.
  • Enter the main event loop of Application object.
import wx 
 
app = wx.App() 
window = wx.Frame(None, title = "wxPython Frame", size = (300,200)) 
panel = wx.Panel(window) 
label = wx.StaticText(panel, label = "Hello World", pos = (100,50)) 
window.Show(True) 
app.MainLoop()
The above code produces the following output −
Hello World wxFrame object is the most commonly employed top level window. It is derived from wxWindow class. A frame is a window whose size and position can be changed by the user. It has a title bar and control buttons. If required, other components like menu bar, toolbar and status bar can be enabled. A wxFrame window can contain any frame that is not a dialog or another frame.

wxPython - GUI Builder Tools

Creating a good looking GUI by manual coding can be tedious. A visual GUI designer tool is always handy. Many GUI development IDEs targeted at wxPython are available. Following are some of them −
  • wxFormBuilder
  • wxDesigner
  • wxGlade
  • BoaConstructor
  • gui2py
wxFormBuilder is an open source, cross-platform WYSIWYG GUI builder that can translate the wxWidget GUI design into C++, Python, PHP or XML format. A brief introduction to usage of wxFormBuilder is given here.
First of all the latest version of wxFormBuilder needs to be downloaded and installed from http://sourceforge.net/projects/wxformbuilder/. On opening the application, a new project with blank grey area at the center appears.
Give a suitable name to the project and choose Python as code generation language. This is done in the Object properties window as shown in the following image −
Object Properties Then from ‘Forms’ tab of components palette, choose Frame.
Choose Frame Add a vertical wxBoxSizer from ‘Layouts’ tab.
Add wxBoxSizer Add necessary controls in the Box with suitable captions. Here, a StaticText (label), two TextCtrl objects (text boxes) and a wxButton object are added. The frame looks like the following image −
Add Controls Enable Expand and Stretch on these three controls. In the object properties for wxButton object, assign a function findsquare() to OnButtonClick event.
Three Controls Save the project and press F8 to generate Python code for developed GUI. Let the generated file be named as Demo.py
In the executable Python script, import demo.py and define FindSquare() function. Declare Application object and start a main event loop. Following is the executable code −
import wx 
  
#import the newly created GUI file 
import demo  
class CalcFrame(demo.MyFrame1): 
   def __init__(self,parent): 
      demo.MyFrame1.__init__(self,parent)  
  
   def FindSquare(self,event): 
      num = int(self.m_textCtrl1.GetValue()) 
      self.m_textCtrl2.SetValue (str(num*num)) 
        
app = wx.App(False) 
frame = CalcFrame(None) 
frame.Show(True) 
#start the applications 
app.MainLoop() 
The above code produces the following output −
GUI Builder Output

wxPython - Major Classes

Original wxWidgets (written in C++) is a huge class library. GUI classes from this library are ported to Python with wxPython module, which tries to mirror the original wxWidgets library as close as possible. So, wx.Frame class in wxPython acts much in the same way as wxFrame class in its C++ version.
wxObject is the base for most of the classes. An object of wxApp (wx.App in wxPython) represents the application itself. After generating the GUI, application enters in an event loop by MainLoop() method. Following diagrams depict the class hierarchy of most commonly used GUI classes included in wxPython.
wxWindow Hierarchy wxGDIObject Hierarchy wxSizer Hierarchy wxButton Hierarchy
S.N. Classes & Description
1 wx.Frame wx.Frame Class has a default constructor with no arguments.
2 wx.Panel wx.Panel class is usually put inside a wxFrame object. This class is also inherited from wxWindow class.
3 wx.StaticText wx.StaticText class object presents a control holding such read-only text. It can be termed as a passive control since it doesn’t produce any event.
4 TextCtrl In wxPython, an object of wx.TextCtrl class serves this purpose. It is a control in which the text can be displayed and edited.
5 RadioButton & RadioBox Each button, an object of wx.RadioButton class carries a text label next to a round button. wxPython API also consists of wx.RadioBox class. Its object offers a border and label to the group.
6 wx.CheckBox A checkbox displays a small labeled rectangular box. When clicked, a checkmark appears inside the rectangle to indicate that a choice is made.
7 ComboBox & Choice Class A wx.ComboBox object presents a list of items to select from. It can be configured to be a dropdown list or with permanent display. wxPython API contains a wx.Choice class, whose object is also a dropdown list, which is permanently read-only.
8 Wx.Gauge Wx.Gauge class object shows a vertical or horizontal bar, which graphically shows incrementing quantity.
9 wx.Slider wxPython API contains wx.Slider class. It offers same functionality as that of Scrollbar. Slider offers a convenient way to handle dragging the handle by slider specific wx.EVT_SLIDER event binder.
10 wx.MenuBar A horizontal bar just below the title bar of a top level window is reserved to display a series of menus. It is an object of wx.MenuBar class in wxPython API.
11 wx.Toolbar If the style parameter of wx.Toolbar object is set to wx.TB_DOCKABLE, it becomes dockable. A floating toolbar can also be constructed using wxPython’s AUIToolBar class.
12 Wx.Dialog Although a Dialog class object appears like a Frame, it is normally used as a pop-up window on top of a parent frame. The objective of a Dialog is to collect some data from the user and send it to the parent frame.
13 wx.Notebook wx.Notebook widget presents a tabbed control. One Notebook object in a frame has one or more tabs (called Pages), each of them having a panel showing the layout of controls.
14 wx.SplitterWindow Object of this class is a layout manager, which holds two subwindows whose size can be changed dynamically by dragging the boundaries between them. The Splitter control gives a handle that can be dragged to resize the controls.
15 HTMLWindow wxHTML library contains classes for parsing and displaying HTML content. Although this is not intended to be a full-featured browser, wx.HtmlWindow object is a generic HTML viewer.
16 ListBox & ListCtrl A wx.ListBox widget presents a vertically scrollable list of strings. By default, a single item in the list is selectable. ListCtrl widget is a highly enhanced list display and selection tool. List of more than one column can be displayed in Report view, List view or Icon view.

wxPython - Event Handling

Unlike a console mode application, which is executed in a sequential manner, a GUI based application is event driven. Functions or methods are executed in response to user’s actions like clicking a button, selecting an item from collection or mouse click, etc., called events.
Data pertaining to an event which takes place during the application’s runtime is stored as object of a subclass derived from wx.Event. A display control (such as Button) is the source of event of a particular type and produces an object of Event class associated to it. For instance, click of a button emits a wx.CommandEvent. This event data is dispatched to event handler method in the program. wxPython has many predefined event binders. An Event binder encapsulates relationship between a specific widget (control), its associated event type and the event handler method.
For example, to call OnClick() method of the program on a button’s click event, the following statement is required −
self.b1.Bind(EVT_BUTTON, OnClick)
Bind() method is inherited by all display objects from wx.EvtHandler class. EVT_.BUTTON here is the binder, which associates button click event to OnClick() method.

Example

In the following example, the MoveEvent, caused by dragging the top level window – a wx.Frame object in this case – is connected to OnMove() method using wx.EVT_MOVE binder. The code displays a window. If it is moved using mouse, its instantaneous coordinates are displayed on the console.
import wx
  
class Example(wx.Frame): 
            
   def __init__(self, *args, **kw): 
      super(Example, self).__init__(*args, **kw)  
      self.InitUI() 
           
   def InitUI(self): 
      self.Bind(wx.EVT_MOVE, self.OnMove) 
      self.SetSize((250, 180)) 
      self.SetTitle('Move event') 
      self.Centre() 
      self.Show(True)
     
   def OnMove(self, e): 
      x, y = e.GetPosition() 
      print "current window position x = ",x," y= ",y 
         
ex = wx.App() 
Example(None) 
ex.MainLoop()   
The above code produces the following output −
Move Event current window position x = 562 y = 309
current window position x = 562 y = 309
current window position x = 326 y = 304
current window position x = 384 y = 240
current window position x = 173 y = 408
current window position x = 226 y = 30
current window position x = 481 y = 80
Some of the subclasses inherited from wx.Event are listed in the following table −
S.N. Events & Description
1 wxKeyEvent
Occurs when a key is presses or released
2 wxPaintEvent
Is generated whenever contents of the window needs to be redrawn
3 wxMouseEvent
Contains data about any event due to mouse activity like mouse button pressed or dragged
4 wxScrollEvent
Associated with scrollable controls like wxScrollbar and wxSlider
5 wxCommandEvent
Contains event data originating from many widgets such as button, dialogs, clipboard, etc.
6 wxMenuEvent
Different menu-related events excluding menu command button click
7 wxColourPickerEvent
wxColourPickerCtrl generated events
8 wxDirFilePickerEvent
Events generated by FileDialog and DirDialog
Events in wxPython are of two types. Basic events and Command events. A basic event stays local to the window in which it originates. Most of the wxWidgets generate command events. A command event can be propagated to window or windows, which are above the source window in class hierarchy.

Example

Following is a simple example of event propagation. The complete code is −
import wx
  
class MyPanel(wx.Panel): 
     
   def __init__(self, parent): 
      super(MyPanel, self).__init__(parent)
  
      b = wx.Button(self, label = 'Btn', pos = (100,100)) 
      b.Bind(wx.EVT_BUTTON, self.btnclk) 
      self.Bind(wx.EVT_BUTTON, self.OnButtonClicked) 
  
   def OnButtonClicked(self, e): 
         
      print 'Panel received click event. propagated to Frame class' 
      e.Skip()  
  
   def btnclk(self,e): 
      print "Button received click event. propagated to Panel class" 
      e.Skip()
  
class Example(wx.Frame):

   def __init__(self,parent): 
      super(Example, self).__init__(parent)  
         
      self.InitUI() 

   def InitUI(self):
 
      mpnl = MyPanel(self) 
      self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)
  
      self.SetTitle('Event propagation demo') 
      self.Centre() 
      self.Show(True)
  
   def OnButtonClicked(self, e): 
         
      print 'click event received by frame class' 
      e.Skip()
  
ex = wx.App() 
Example(None) 
ex.MainLoop()
In the above code, there are two classes. MyPanel, a wx.Panel subclass and Example, a wx.Frame subclass which is the top level window for the program. A button is placed in the panel.
This Button object is bound to an event handler btnclk() which propagates it to parent class (MyPanel in this case). Button click generates a CommandEvent which can be propagated to its parent by Skip() method.
MyPanel class object also binds the received event to another handler OnButtonClicked(). This function in turn transmits to its parent, the Example class. The above code produces the following output −
Event Handling Output
Button received click event. Propagated to Panel class. 
Panel received click event. Propagated to Frame class. 
Click event received by frame class.

No comments:

Post a Comment