Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Gauld A.Learning to program (Python)_1.pdf
Скачиваний:
23
Добавлен:
23.08.2013
Размер:
1.34 Mб
Скачать

The Tcl view

Since we've been comparing Python with Tcl throughout the early part of this tutor it seems sensible to show you what the early Label and Button example looks like in the original Tcl/Tk form:

Label .lHello -text "Hello World"

Button .bHello -text Quit -command "exit" wm title . Hello

pack .lHello .bHello

As you can see it is very concise. The widget heirarchy is formed by a naming convention with '.' as the top level widget. As is usual in Tcl the widgets are commands with the properties passed as arguments. Hopefully the translation of widget parameters to Python named arguments is fairly obvious. This means that you can use the Tcl/Tk documentation(of which there is a lot!) to help solve problems with Tkinter programming, mostly its an obvious translation.

That's as far as I'm going with Tcl/Tk here. Before we finish though I'll show you a common technique for bundling Tkinter GUI applications as objects.

Wrapping Applications as Objects

It's common when programming GUI's to wrap the entire application as a class. This begs the question, how do we fit the widgets of a Tkinter application into this class structure? There are two choices, we either decide to make the application itself as a subclass of a Tkinter Frame or have a member field store a reference to the top level window. The latter approach is the one most commonly used in other toolkits so that's the approach we'll use here. If you want to see the first approach in action go back and look at the example in the Event Driven Programming topic. (That example also illustrates the basic use of the incredibly versatile Tkinter Text widget)

I will convert the example above using an Entry field, a Clear button and a Quit button to an OO structure. First we create an Application class and within the constructor assemble the visual parts of the GUI.

We assign the resultant Frame to self.mainWindow, thus allowing other methods of the class access to the top level Frame. Other widgets that we may need to access (such as the Entry field) are likewise assigned to member variables of the Frame. Using this technique the event handlers become methods of the application class and all have access to any other data members of the application (although in this case there are none) through the self reference. This provides seamless integration of the GUI with the underlying application objects:

90

from Tkinter import *

class ClearApp:

def __init__(self, parent=0): self.mainWindow = Frame(parent)

#Create the entry widget self.entry = Entry(self.mainWindow) self.entry.insert(0,"Hello world") self.entry.pack(fill=X)

#now add the 2 buttons

#we use a nested frame pair to give a grooved effect fOuter = Frame(self.mainWindow, border=1, relief="sunken") fButtons = Frame(fOuter, border=1, relief="raised") bClear = Button(fButtons, text="Clear",

width=8, height=1, command=self.clearText) bQuit = Button(fButtons, text="Quit",

width=8, height=1, command=self.mainWindow.quit)

bClear.pack(side="left", padx=15, pady=1) bQuit.pack(side="right", padx=15, pady=1) fButtons.pack(fill=X) fOuter.pack(fill=X) self.mainWindow.pack()

# set the title self.mainWindow.master.title("Clear")

def clearText(self): self.entry.delete(0,END)

app = ClearApp() app.mainWindow.mainloop()

Here's the result:

The result looks remarkably like the previous incarnation although I have tweaked the lower frame to give it a nice grooved finish and I've supplied widths to the buttons to make them look more similar to the wxPython example below.

Of course its not just the main application that we can wrap up as an object. We could create a class based around a Frame containing a standard set of buttons and reuse that class in building dialog windows say. We could even create whole dialogs and use them across several projects. Or we can extend the capabilities of the standard widgets by subclassing them - maybe to create a button that changes colour depending on its state. This is what has been done with the Python Mega Widgets (PMW) which is an extension to Tkinter which you can download.

91

An alternative - wxPython

There are many other GUI toolkits available but one of the most popular is the wxPython toolkit which is, in turn, a wrapper for the C++ toolkit wxWindows. wxPython is much more typical than Tkinter of GUI toolkits in general. It also provides more standard functionality than Tk "out of the box" - things like tooltips, status bars etc which have to be hand crafted in Tkinter. We'll use wxWindows to recreate the simple "Hello World" Label and Button example above.

I won't go through this in detail, if you do want to know more about how wxPython works you will need to download the package from the wxPython website.

In general terms the toolkit defines a framework which allows us to create windows and populate them with controls and to bind methods to those controls. It is fully object oriented so you should use methods rather than functions. The example looks like this:

from wxPython.wx import *

# --- Define a custom Frame, this will become the main window ---

class HelloFrame(wxFrame):

def __init__(self, parent, ID, title, pos, size): wxFrame.__init__(self, parent, ID, title, pos, size)

#we need a panel to get the right background panel = wxPanel(self, -1)

#Now create the text and button widgets

self.tHello = wxTextCtrl(panel, -1, "Hello world", (3,3), (185,22))

button = wxButton(panel, 10, "Clear", (15, 32)) button = wxButton(panel, 20, "Quit", (100, 32))

# now bind the button to the handler EVT_BUTTON(self, 10, self.OnClear) EVT_BUTTON(self, 20, self.OnQuit)

# these are our event handlers def OnClear(self, event):

self.tHello.Clear()

def OnQuit(self, event): self.Destroy()

#--- Define the Application Object ---

#Note that all wxPython programs MUST define an

#application class derived from wxApp

class HelloApp(wxApp): def OnInit(self):

frame = HelloFrame(NULL, -1, "Hello", (200,50),(200,90) ) frame.Show(true)

# self.setTopWindow(frame) return true

# create instance and start the event loop HelloApp().MainLoop()

And it looks like this:

92

Points to note are the use of a naming convention for the methods that get called by the framework - OnXXXX. Also note the EVT_XXX functions to bind events to widgets - there is a whole family of these. wxPython has a vast array of widgets, far more than Tkinter, and with them you can build quite sophisticated GUIs. Unfortunately they tend to use a coordinate based placement scheme which becomes very tedious after a while. It is possible to use a scheme very similar to the Tkinter packer but its not so well documented. There is a commercial GUI builder available and hopefully someone will soon provide a free one too.

Incidentally it might be of interest to note that this and the very similar Tkinter example above have both got exactly the same number of lines of executable code - 21.

In conclusion, if you just want a quick GUI front end to a text based tool then Tkinter should meet your needs with minimal effort. If you want to build full featured cross platform GUI applications look more closely at wxPython.

Other toolkits include MFC, pyQt, pyGTK, the latter is Linux only at present although potentially could be ported to Windows too since the underlying GTK library already runs on Windows. Finally there is curses which is a kind of text based GUI! Many of the lessons we've learned with Tkinter apply to all of these toolkits but each has its own characteristics and foibles. Pick one, get to know it and enjoy the wacky world of GUI design.

That's enough for now. This wasn't meant to be a Tkinter reference page, just enough to get you started. See the Tkinter section of the Python web pages for links to other Tkinter resources.

There are also several books on using Tcl/Tk and at least one on Tkinter. I will however come back to Tkinter in the case study, where I illustrate one way of encapsulating a batch mode program in a GUI for improved usability.

93