Title: Anygui Tutorial Author: Magnus Lie Hetland Date: 2002-01-04 1. Introduction Anygui is a GUI package for Python that lets you write GUI programs that will run in any Python installation, using the available backend packages (such as Tkinter or wxPython) and resort to text-based GUI emulation (using curses or plain standard input/output) when no known GUI backend is available. This tutorial will show you how to use Anygui to build a simple application which has a single window with a text field and a button. Pressing the button will insert a random sentence into the text field. To follow this tutorial, you'll need a Python interpreter and the latest Anygui distribution. Python can be downloaded from the Python website[1] and Anygui can be downloaded from the Anygui website[2]. 2. Creating Random Sentences Before we make the GUI, we'll need some functionality. Let's keep it simple: from random import choice nouns = ['can of spam', 'cardinal', 'machine that goes "ping"'] adjectives = ['big', 'little', 'pink', 'tasty'] verbs = ['ate', 'got', 'imitated'] def sentence(): words = ['the', choice(adjectives), choice(nouns), choice(verbs), 'the', choice(adjectives), choice(nouns)] return ' '.join(words) To customise this, simply edit the word lists to taste. With the current setup, it works like this: >>> sentence() 'the big cardinal got the tasty machine that goes "ping"' 3. Creating a Window and Running the Application Now we need an application with a single window. How do we do that? It's really intuitive: from anygui import * win = Window() app = Application() app.add(win) There; we've created a Window object, an Application object, and added the Window to the Application (otherwise it wouldn't show up anywhere). This won't do anything by itself; we need to tell the Application to start running, which will "freeze" the script and start up a GUI: app.run() print "We're done!" I just added the print statement to show how this works. If you run the script, you will see that an empty window appears, and that's about it. But when you close that window, the Application stops running the GUI, and the run() method will return, and finally the program will print "We're done!" 4. Adding a Button and a TextField Now that you've seen me add a Window to the Application, I'm sure you can guess how to add a Button and a TextField to the Window, but I'll show you anyway: btn = Button() win.add(btn) txt = TextField() win.add(txt) Nothing fancy here. However, if you actually use this code, you'll probably notice a two things: 1. The button will simply be called "Button" 2. The positioning will be really stupid So what do we do to change that? 5. Attributes The clue to customising objects in Anygui is attributes. Most properties of any object can be modified simply by setting an attribute; for instance, to set the text of our Button object, we can simply do btn.text = 'Click Me' Simple, huh? Similarly, we can set the components' size and position: btn.x = 10 btn.y = 10 btn.width = win.width - 20 txt.x = 10 txt.y = btn.height + 20 txt.width = btn.width Similarly we could set the window size and position etc. Feel free to experiment to make the application look more sensible. There are a few shortcuts that makes specifying position and geometry a bit easier: btn.geometry = x, y, width, height is equivalent to setting x, y, width, height separately; similarly we have btn.position = x, y and btn.size = width, height If you don't want to set all the attributes separately, you can also supply them as keyword arguments to the object's constructor: btn = Button(text='Click Me', x=10, y=10, ...) 6. Advanced Layout Specifying the size and position of the components can be a bit tedious, but it is also a technique with one serious limitation: If you resize the window, the components' geometry won't change. To To use a layout manager, simply assign it to a Window's layout attribute: win.layout = SomeLayoutManager() The default layout manager is Placer, and we'll only look at that here (which means that you can leave your Window's layout property alone). (Note: Layout managers can be used with any Frame, not just Windows. Frames in general aren't discussed in this tutorial.) To give the layout manager something to work with, simply use some keyword arguments in the add method. You can combine this with setting the component geometry in any way you like; the layout manager simply updates the geometry when the surrounding Window (or Frame) is resized. Let's say we want the following placement: 1. The text field is placed on top, with a 10 point margin 2. The text field should be resized to fill the window horizontally 3. The button should have a fixed size, but be moved to keep it 10 points from the right edge of the window We can do that like this: win.add(txt, top=10, left=10, right=10, hstretch=1) Here we are simply telling the layout manager that the top, left, and right margins (the distance to the surrounding window) of the text field should be set to 10, and that the text field should be stretched horizontally (hstretch) to keep these margins. (There is also a vstretch argument for vertical stretching.) The button is placed like this: win.add(btn, top=(txt,10), right=10, hmove=1) Here we say that it should be positioned with its top 10 points below the text field by setting top to the tuple (txt,10). We also say that it should be positioned 10 points from the right edge of the window, and that it should be moved horizontally to keep that distance (hmove=1). Try it out. Change it and see what happend. Oh, yeah; there is also a keyword argument called bottom . (Note: TextField is meant to contain a single line of text and therefore isn't meant to be resized vertically. If you want to experiment with vstretch, you could use TextArea instead, which is meant to contain arbitrary text.) 7. Handling Events When certain events occur, Anygui may send a signal to your program which you can choose to react to. (We also call this "sending an event".) For instance, when the user clicks a button, an event of the type 'click' is sent automatically, with the button as the source. To respond to it, you just have to write a function (or method) containing the action to be performed (called the "event handler") and link it to the button: def handler(**kw): txt.text = sentence() link(btn, 'click', handler) Here we have explicitly said that the handler should be called when an event of type 'click' occurs. This is the default event type of buttons, which means that we could also have used the type called 'default', like this: link(btn, 'default', handler) The nice thing about this is that 'default' always can be omitted, so we just write: link(btn, handler) Try it; when you click the button, the text field will be filled with a random sentence. Click it again, and a new sentence appears. Cool, huh? (Note: Event handlers receive information about the event through keyword arguments, such as event type, the time when the event occurred etc. We simply ignore all that here, using the **kw syntax to allow any keywords.) 9. Further Exploration After this short tutorial you should be able to write quite complex Anygui programs. To aid you in your exploration here is some more information: Common attributes: x -- x-coordinate of upper left corner y -- y-coordinate of upper left corner position -- equivalent to (x, y) width -- component width height -- component height size -- equivalent to (width, height) geometry -- equivalent to (x, y, width, height) visible -- whether the component is visible enabled -- whether the component is enabled text -- text associated with the component Some component types (and additional attributes and methods): Button -- clickable button CheckBox -- toggle button cbx.on -- the state of the CheckBox Frame -- "container" for other components frm.add() -- similar to win.add() Label -- a simple one-line text label ListBox -- selectable list of strings lbx.items -- the items in the ListBox lbx.selection -- the currently selected item RadioButton -- a toggle button (should be in a RadioGroup) rbn.group -- the RadioGroup of the RadioButton RadioGroup -- group of RadioButtons grp.add() -- used for adding RadioButtons TextArea -- multiline text component txt.selection -- tuple (start, end) containing selection TextField -- single-line text component txt.selection -- tuple (start, end) containing selection Window -- a top-level window win.title -- the title of the window For more information about these classes, and about such things as the Anygui Model-View-Controller mechanism, please consult the Anygui Reference Manual, available in the disribution or from the Anygui website[2]. A. The Program from random import choice from anygui import * nouns = ['can of spam', 'cardinal', 'machine that goes "ping"'] adjectives = ['big', 'little', 'pink', 'tasty'] verbs = ['ate', 'got', 'imitated'] def sentence(): words = ['the', choice(adjectives), choice(nouns), choice(verbs), 'the', choice(adjectives), choice(nouns)] return ' '.join(words) win = Window() btn = Button(text='Click Me') txt = TextField() win.add(txt, top=10, left=10, right=10, hstretch=1) win.add(btn, top=(txt,10), right=10, hmove=1) win.height = txt.height + btn.height + 30 def handler(**kw): txt.text = sentence() link(btn, 'click', handler) app = Application() app.add(win) app.run() B. References [1] http://www.python.org [2] http://www.anygui.org