Wax primer: A simple editor |
:: Email ::
Download area
|
This document illustrates some of the basics of Wax. As an example program, we're going to make a simple editor. I'm going to build it step by step; you are encouraged to apply the changes incrementally and run the code after every step. Every Wax application needs at least an Application object, using a Frame. A skeleton app would look like this: from wax import *
class MainFrame(Frame):
pass
app = Application(MainFrame)
app.Run()
app = Application(MainFrame, title="A simple editor") For our editor widget, we're going to use a simple TextBox, which is based on wxPython's wxTextCtrl. You add controls to a Frame by overriding its Body() method. Let's start simple: class MainFrame(Frame):
def Body(self):
self.textbox = TextBox(self, multiline=1, wrap=0)
self.AddComponent(self.textbox)
Normally a little bit more code is needed, but since the TextBox is currently our only control, we get away with coding it like this. The TextBox automatically fills up the whole window and resizes if the window resizes. Like most (all?) GUI toolkits, when a control is created, a reference to its parent is passed. In this case, controls that belong to MainFrame are passed I don't like the font, though. Let's set a fixed-width font for the TextBox. Add this code after the import statement: FIXED_FONT = ('Courier New', 10)
# note that this used to be Font('Courier New', 10) in older
# versions, but this isn't allowed anymore in recent versions
# of wxPython
and change the code in Body() to this: def Body(self):
self.textbox = TextBox(self, multiline=1, wrap=0)
self.textbox.SetFont(FIXED_FONT)
self.AddComponent(self.textbox)
OK, now we have an editor. But it's not very useful. It cannot load or save anything. It would be a good idea to add a menu with these options. This is the code that creates the menu (CreateMenu is a method of MainFrame, of course): def CreateMenu(self):
menubar = MenuBar()
menu1 = Menu(self)
menu1.Append("&New", self.New, "Create a new file")
menu1.Append("&Open", self.Open, "Open a file")
menu1.Append("&Save", self.Save, "Save a file")
menubar.Append(menu1, "&File")
self.SetMenuBar(menubar)
Create dummy methods for New, Open and Save (again in MainFrame): def New(self, event): pass
def Open(self, event): pass
def Save(self, event): pass
And change Body() to: def Body(self):
self.CreateMenu()
self.textbox = TextBox(self, multiline=1, wrap=1)
self.textbox.SetFont(FIXED_FONT)
self.AddComponent(self.textbox)
A line like The resulting code works, and you will notice that the window now sports a menu bar. Clicking on the items doesn't do anything yet, because we associated the menu items with empty methods. That's going to change, though. For this example, I will use simple methods:
First, we need a def Body(self):
self.filename = None
# other code here...
Implementing the New() method is easy: def New(self, event):
self.textbox.Clear()
self.filename = None
Note that most Wax controls are derived from wxPython controls, and as such have the same methods (plus some more, usually). Here, TextBox.Clear() is the same as wxTextCtrl.Clear(). Writing the Open() method will be a bit more challenging, since it requires a dialog. In this case, the FileDialog class. Fortunately, it's easy to use. Like in wxPython and many other GUI toolkits, this is how you use dialogs:
The actual code looks like this: def Open(self, event):
dlg = FileDialog(self, open=1)
result = dlg.ShowModal()
if result == 'ok':
filename = dlg.GetPaths()[0]
self._OpenFile(filename)
dlg.Destroy()
(We cannot run this yet until we have written the _OpenFile method.) Some comments:
Note that in case something goes wrong in, say, _OpenFile, an exception will occur and the dialog will not be destroyed. To prevent this from happening, people usually write such code like this: def Open(self, event):
dlg = FileDialog(self, open=1)
try:
result = dlg.ShowModal()
if result == 'ok':
filename = dlg.GetPaths()[0]
self._OpenFile(filename)
finally:
dlg.Destroy()
Now for the implementation of _OpenFile. It should simply take a filename, load that file into the TextBox, and set the internal filename. This uses the Clear() and AppendText() methods, well known from wxTextCtrl: def _OpenFile(self, filename):
self.filename = filename
f = open(filename, 'r')
data = f.read()
f.close()
self.textbox.Clear()
self.textbox.AppendText(data)
The code should now work. Try it, select Open in the File menu, select a file, and its contents should appear in the TextBox. Now that this is done, the code for Save is not difficult: def Save(self, event):
if self.filename:
self._SaveFile(self.filename)
else:
dlg = FileDialog(self, save=1)
try:
result = dlg.ShowModal()
if result == 'ok':
filename = dlg.GetPaths()[0]
self.filename = filename
self._SaveFile(filename)
finally:
dlg.Destroy()
def _SaveFile(self, filename):
f = open(filename, 'w')
f.write(self.textbox.GetValue())
f.close()
Ta-da! A working editor, in ~70 lines of code. Nothing fancy, but it illustrates the power of Wax. (And of wxPython, of course.) In part 2, we will soup up this editor, by adding a few thingies, like a statusbar, toolbar, shortcut keys, and more. Your code should look like this: from wax import * |