wxGlade tutorial - First steps
(Contributed by Chris Lale, chrislale AT users DOT berlios DOT de)
Table of Contents:
Create an application in wxglade
There are three windows:
- wxGlade v0.4.1 (the main window - a toolbox of widgets)
- wxGlade: Tree (tree view of widgets).
Properties - <app>
Now create an application. Select the first widget in the main window (Add a Frame), by clicking on it.
in the "Select frame class" popup choose
Base class: wxFrame
A new, empty window appears showing the design of your application. Its just an empty frame:
<Design> - frame_1
The Tree shows that the application contains one frame (window). wxGlade has automatically added a sizer to contain any other widgets you may wish to add later.
Set properties for the frame
In the Tree window, select frame_1(MyFrame).
In the Properties window, set the title. The title will appear at the top of the frame when you run the application.
Properties -> Widget -> Title: simple-glade
In the Properties window, set a size for the frame.
Properties -> Common -> Size: (tick the box).
Width and height sizes become active. If you are not happy with the sizes, change the size of the design window using the mouse. Alternatively, type new numbers into the Properties window.
Now is a good time to save the project. In the main window
File -> Save -> /path/to/your/project/simple-glade.wxg
Generate the Python code
In the Tree window, select Application.
In the Properties window, select
Top window: frame_1
Output path: /path/to/your/project/simple-glade.py
Run the application
Change to the directory containing simple-glade.py. Run the file from the commandline
Alternatively you can open the file in Idle and press F5 to run it.
The application is an empty window. It has a title, and you can move, resize and close it just like any other application.
Understanding the code
Open the simple-glade.py file in Idle or a text editor. The file is a Python module that can be run as a Python program.
Line 1 is the "hash-bang" line.
This line enables the file to be run directly (./simple-glade.py), rather than passing it to the Python interpreter (python simple-glade.py).
Line 5: import the Python GUI package.
1 import wx
Imports wxPython classes, constants, etc into the module's namespace.
Lines 7-31: create a class for the frame
This section creates a new frame class MyFrame, derived from the wxPython class wx.Frame
There are three methods. First is the frame's __init__() method.
Sets the frame's style to the built-in wx.DEFAULT_FRAME_STYLE. This was the default that you accepted in wxGlade.
Calls the base class' __init__() method to create the frame.
- Calls its own methods to set properties for and do layout of the frame.
The next method sets the frame's properties.
These are the values for title and frame size that you chose in wxGlade. They are used to set the properties of the class MyFrame. MyFrame inherits these properties from the wx.Frame class, which in turn inherits them from the wx.Window base class. (Ref: http://www.wxpython.org/docs/api/wx.Window-class.html)
The third method defines the frame's layout.
sizer_1 = wx.BoxSizer(wx.VERTICAL) creates the sizer sizer_1, and sets its style to the built-in wx.VERTICAL. This is the default set by wxGlade. You did not have a choice for this sizer.
SetAutoLayout(True) determines that the Layout function will be called automatically when the window is resized.
SetSizer(sizer_1) sets the window's layout to consist only of the sizer sizer_1. Layout() invokes the sizer-based algorithm for this window.
SetAutoLayout(), SetSizer() and Layout() are methods inherited from the class wx.Window (see http://www.wxpython.org/docs/api/wx.Window-class.html).
Warning:: the calls to SetAutoLayout(), Layout(), and Fit() (the latter appears in code generated by wxGlade > 0.4) are unnecessary; only one Fit() is necessary, at the top level (frame). This is just a performance issue.
Warning:: In wxGlade > 0.4, the code generated also contains a call to sizer_1.SetSizeHints(self) which is WRONG. Actually, a more complex example would show that SetSizeHints() is called on most sizers. Such a call makes sense only for top-level windows (typically) and actually prevents proper sizing of your windows. E.g., if you have custom panels that involve dynamically changing the contents of your frame, then having the sizers SetSizeHints() called will prevent the sizers from computing the new "best fit". (Ref a post on wxpython-users mailing list, dated 2006-04-20; same post also archived here). Once I removed *all* the SetSizeHints() calls that wxGlade was putting in my files, the layouts were behaving as expected. You can also modify the source code of wxGlade: the file is wxGlade/edit_sizers/sizers_codegen.py; comment out the lines that have SetSizeHints(), in the three classes Python*SizerBuilder (one line per class). While you're at it, comment out the lines just above those that have SetAutoLayout() (if you also uncomment the ones that have Fit(), then you will be missing one call to Fit() in your top-level frame; which in the typical case will be necessary anyhow).
Lines 34-42 create a class for the application.
It creates a new application class MyApp, derived from the wxPython class wx.App. It contains one method - the application's OnInit() method.
This method is the start of the application (like "main" in C).
wx.InitAllImageHandlers() enables the module to handle a variety of image file formats (see http://wxwidgets.org/manuals/2.6.1/wx_appinifunctions.html#wxinitallimagehandlers).
frame_1 = MyFrame(None, -1, "") creates the application's window with parent=None, id=-1 (ie id set automatically) and title="" (ie no title). (More details of the default constructor parameters at http://wxwidgets.org/manuals/2.6.1/wx_wxframe.html#wxframector.)
self.SetTopWindow(frame_1) lets wxWidgets know which is the main window. (More details at http://wxwidgets.org/manuals/2.6.1/wx_wxapp.html#wxappsettopwindow.)
frame_1.Show() shows the window. Without this, the window would remain invisible. Note: frame_1.Show() is the same as frame_1.Show(True); frame_1.Show(False) would hide the window. (See http://www.wxpython.org/docs/api/wx.Window-class.html.)
Lines 44-46: the if __name__ trick
The simple-glade.py file is a python module. It can be imported into other python programs. The bottom three lines are a trick to enable the program to be run as a standalone program. If you run simple-glade.py directly, its __name__ attribute is __main__, so app = MyApp(0) and app.MainLoop() are invoked.
The gui platform and all the widgets have now been created and initialised.
app = MyApp(0) creates an instance of the application class MyApp, and calls the OnInit() method. It then sets the application's main window - there is only one window in this case, of course.
app.MainLoop() starts the event loop which continues until the application terminates or all the top level windows are closed. The event loop monitors the gui continuously. When it detects an event (eg a button press), it executes any code that has been bound to that event. Of course, we have not added any code to this example since there are no widgets to generate events!
Appendix: The complete code
1 #!/usr/bin/env python 2 # -*- coding: ISO-8859-1 -*- 3 # generated by wxGlade 0.4.1 on Fri Mar 24 14:22:53 2006 4 5 import wx 6 7 class MyFrame(wx.Frame): 8 def __init__(self, *args, **kwds): 9 # begin wxGlade: MyFrame.__init__ 10 kwds["style"] = wx.DEFAULT_FRAME_STYLE 11 wx.Frame.__init__(self, *args, **kwds) 12 13 self.__set_properties() 14 self.__do_layout() 15 # end wxGlade 16 17 def __set_properties(self): 18 # begin wxGlade: MyFrame.__set_properties 19 self.SetTitle("simple-glade") 20 self.SetSize((343, 510)) 21 # end wxGlade 22 23 def __do_layout(self): 24 # begin wxGlade: MyFrame.__do_layout 25 sizer_1 = wx.BoxSizer(wx.VERTICAL) 26 self.SetAutoLayout(True) 27 self.SetSizer(sizer_1) 28 self.Layout() 29 # end wxGlade 30 31 # end of class MyFrame 32 33 34 class MyApp(wx.App): 35 def OnInit(self): 36 wx.InitAllImageHandlers() 37 frame_1 = MyFrame(None, -1, "") 38 self.SetTopWindow(frame_1) 39 frame_1.Show() 40 return 1 41 42 # end of class MyApp 43 44 if __name__ == "__main__": 45 app = MyApp(0) 46 app.MainLoop()