18.3. Tkinter Examples

18.3.1. Label Widget

In Example 18.1, we present tkhello1.py, the Tkinter version of “Hello World!” In particular, it shows you how a Tkinter application is set up and highlights the Label widget

Listing 18.1. Label Widget Demo (tkhello1.py)

Our first Tkinter example is… what else? “Hello World!” In particular, we introduce our first widget, the Label.

1  #!/usr/bin/env python
2  
3  import Tkinter
4
5  top = Tkinter.Tk()
6  label = Tkinter.Label(top, text='Hello World!')
7  label.pack()
8  Tkinter.mainloop()

In the first line, we create our top-level window. That is followed by our Label widget containing the all-too-famous string. We instruct the packer to manage and display our widget, and finally call mainloop() to run our GUI application. Figure 18-1 shows what you will see when you run this GUI application.

Figure 18-1. Tkinter Label Widget (tkhello1.py)


18.3.2. Button Widget

The next example is pretty much the same as the first. However, instead of a simple text label, we will create a button instead. In Example 18.2 is the source code for tkhello2.py:

Listing 18.2. ButtonWidget Demo (tkhello2.py)

This example is exactly the same as tkhello1.py except that rather than using a Label widget, we create a Button widget.

1  #!/usr/bin/env python
2
3  import Tkinter
4 
5  top = Tkinter.Tk()
6  quit = Tkinter.Button(top, text='Hello World!',
7      command=top.quit)
8  quit.pack()
9  Tkinter.mainloop()

The first few lines are identical. Things differ only when we create the Button widget. Our button has one additional parameter, the Tkinter.quit() method. This installs a callback to our button so that if it is pressed (and released), the entire application will exit. The final two lines are the usual pack() and entering of the mainloop(). This simple button application is shown in Figure 18-2.

Figure 18-2. Tkinter Button Widget (tkhello2.py)


18.3.3. Label and Button Widgets

We combine tkhello1.py and tkhello2.py into tkhello3.py, a script which has both a label and a button. In addition, we are providing more parameters now than before when we were comfortable using all the default arguments which are automatically set for us. The source for tkhello3.py is given in Example 18.3.

Listing 18.3. Label and Button Widget Demo (tkhello3.py)

This example features both a Label and a Button widget. Rather than primarily using default arguments when creating the widget, we are able to specify more now that we know more about Button widgets and how to configure them.

1   #!/usr/bin/env python 
2
3   import Tkinter
4   top = Tkinter.Tk()
5
6   hello = Tkinter.Label(top, text='Hello World!')
7   hello.pack()
8
9   quit = Tkinter.Button(top, text='QUIT',
10      command=top.quit, bg='red', fg='white')
11  quit.pack(fill=Tkinter.X, expand=1)
12
13  Tkinter.mainloop()

Besides additional parameters for the widgets, we also see some arguments for the packer. The fill parameter tells the packer to let the QUIT button take up the rest of the horizontal real estate, and the expand parameter directs the packer to visually fill out the entire horizontal landscape, stretching the button to the left and right sides of the window.

As you can see in Figure 18-3, without any other instructions to the packer, the widgets are placed vertically (on top of each other). Horizontal placement requires creating a new Frame object with which to add the buttons. That frame will take the place of the parent object as a single child object (see the buttons in the listdir.py module, Example 18.5 in Section 18.3.5).

Figure 18-3. Tkinter Label and Button Widgets (tkhello3.py)


18.3.4. Label, Button, and Scale Widgets

Our final trivial example, tkhello4.py, involves the addition of a Scale widget. In particular, the Scale is used to interact with the Label widget. The Scale slider is a tool which controls the size of the text font in the Label widget. The greater the slider position, the larger the font, and the same goes for a lesser position, meaning a smaller font. The code for tkhello4.py is given in Example 18.4.

New features of this script include a resize() callback function (lines 5–7), which is attached to the Scale. This is the code that is activated when the slider on the Scale is moved, resizing the size of the text in the Label.

We also define the size (250×150) of the top-level window (line 10). The final difference between this script and the first three is that we import the attributes from the Tkinter module into our namespace with “from Tkinter import *.” This is mainly due to the fact that this application is larger and involves a large number of references to Tkinter attributes, which would otherwise require their fully-qualified names. The code is shortened a bit and perhaps may not wrap as many lines without importing all the attributes locally.

Listing 18.4. Label, Button, and Scale Demo (tkhello4.py)

Our final introductory widget example introduces the Scale widget and highlights how widgets can “communicate” with each other using callbacks [such as resize()]. The text in the Label widget is affected by actions taken on the Scale widget.

1  #!/usr/bin/env python
2
3  from Tkinter import *
4
5  def resize(ev=None):
6      label.config(font='Helvetica -%d bold' % 
7          scale.get())
8
9  top = Tk()
10 top.geometry('250×150')
11
12 label = Label(top, text='Hello World!',
13     font='Helvetica -12 bold')
14 label.pack(fill=Y, expand=1)
15
16 scale = Scale(top, from_=10, to=40,
17     orient=HORIZONTAL, command=resize)
18 scale.set(12) 
19 scale.pack(fill=X, expand=1) 
20
21 quit = Button(top, text='QUIT', 
22     command=top.quit, activeforeground='white', 
23     activebackground='red') 
24 quit.pack() 
25
26 mainloop()

As you can see from Figure 18-4, both the slider mechanism as well as the current set value show up in the main part of the window.

Figure 18-4. Tkinter Label, Button, and Scale Widgets (tkhello4.py)


18.3.5. Intermediate Tkinter Example

We conclude this section with a larger example, listdir.py. This application is a directory tree traversal tool. It starts in the current directory and provides a file listing. Double-clicking on any other directory in the list causes the tool to change to the new directory as well as replace the original file listing with the files from the new directory. The source code is given below as Example 18.5.

Listing 18.5. File System Traversal GUI (listdir.py)

This slightly more advanced GUI expands on the use of widgets, adding listboxes, text entry fields, and scrollbars to our repertoire. There are also a good number of callbacks such as mouse clicks, key presses, and scrollbar action.

1  #!/usr/bin/env python
2
3  import os
4  from time import sleep
5  from Tkinter import *
6
7  class DirList:
8
9       def __init__(self, initdir=None):
10          self.top = Tk()
11          self.label = Label(self.top, 
12              text='Directory Lister' + ' v1.1')
13          self.label.pack()
14
15          self.cwd=StringVar(self.top)
16
17          self.dirl = Label(self.top, fg='blue',
18              font=('Helvetica', 12, 'bold'))
19          self.dirl.pack()
20
21          self.dirfm = Frame(self.top)
22          self.dirsb = Scrollbar(self.dirfm)
23          self.dirsb.pack(side=RIGHT, fill=Y)
24          self.dirs = Listbox(self.dirfm, height=15,
25              width=50, yscrollcommand=self.dirsb.set)
26          self.dirs.bind('<Double-1>', self.setDirAndGo)
27          self.dirsb.config(command=self.dirs.yview)
28          self.dirs.pack(side=LEFT, fill=BOTH)
29          self.dirfm.pack()
30
31          self.dirn = Entry(self.top, width=50,
32              textvariable=self.cwd)
33          self.dirn.bind('<Return>', self.doLS)
34          self.dirn.pack()
35
36          self.bfm = Frame(self.top)
37          self.clr = Button(self.bfm, text='Clear',
38              command=self.clrDir,
39              activeforeground='white',
40              activebackground='blue')
41          self.ls = Button(self.bfm,
42              text='List.Directory',
43              command=self.doLS,
44              activeforeground='white',
45              activebackground='green')
46          self.quit = Button(self.bfm, text='Quit',
47              command=self.top.quit,
48              activeforeground='white',
49              activebackground='red')
50          self.clr.pack(side=LEFT)
51          self.ls.pack(side=LEFT)
52          self.quit.pack(side=LEFT)
53          self.bfm.pack()
54
55          if initdir:
56              self.cwd.set(os.curdir)
57              self.doLS()
58
59     def clrDir(self, ev=None):
60         self.cwd.set('')
61
62     def setDirAndGo(self, ev=None):
63         self.last = self.cwd.get()
64         self.dirs.config(selectbackground='red')
65         check = self.dirs.get(self.dirs.curselection())
66         if
							not check:
67            check = os.curdir
68         self.cwd.set(check)
69         self.doLS()
70
71     def doLS(self, ev=None):
72         error = ''
73         tdir = self.cwd.get()
74         if
							not tdir: tdir = os.curdir
75
76         if
							not os.path.exists(tdir):
77            error = tdir + ': no such file'
78         elif
							not os.path.isdir(tdir):
79            error = tdir + ': not a directory'
80
81         if error:
82             self.cwd.set(error)
83             self.top.update()
84             sleep(2)
85             if not (hasattr(self, 'last') 
86                 and self.last):
87                 self.last = os.curdir
88             self.cwd.set(self.last)
89             self.dirs.config(
90                 selectbackground='LightSkyBlue')
91             self.top.update()
92             return
93
94         self.cwd.set(
95             'FETCHING DIRECTORY CONTENTS…')
96         self.top.update()
97         dirlist = os listdir(tdir)
98         dirlist sort()
99         os.chdir(tdir)
100        self.dirl.config(text=os.getcwd())
101        self.dirs.delete(0, END)
102        self.dirs.insert(END, os.curdir)
103        self.dirs.insert(END, os.pardir)
104        for eachFile in dirlist:
105            self.dirs.insert(END, eachFile)
106        self.cwd.set(os.curdir)
107        self.dirs.config(
108            selectbackground='LightSkyBlue')
109
110    def main():
111        d = DirList(os.curdir)
112        mainloop()
113
114    if __name__ == '__main__':
115        main()

In Figure 18-5, we present what this GUI looks like in a Windows environment:

Figure 18-5. List Directory GUI Application in Windows (listdir.py)


The Unix version of this application is given in Figure 18-6.

Figure 18-6. List Directory GUI Application in UNIX (listdir.py)


Line-by-line explanation
Lines 1–5

These first few lines contain the usual Unix start-up line and importation of the os module, the time.sleep() function, and all attributes of the Tkinter module.

Lines 9–13

These lines define the constructor for the DirList class, an object which represents our application. The first Label we create contains the main title of the application and the version number.

Lines 15–19

We declare a Tk variable named cwd to hold the name of the directory we are on—we will see where this comes in handy later. Another Label is created to display the name of the current directory.

Lines 21–30

This section defines the core part of our GUI, the Listbox dirs, which contain the list of files of the directory that is being listed. A Scrollbar is employed to allow the user to move through a listing if the number of files exceeds the size of the Listbox. Both of these widgets are contained in a Frame widget. Listbox entries have a callback (setdirandgo) tied to them using the Listbox bind() method.

Binding means to tie a keystroke, mouse action, or some other event to a call back to be executed when such an event is generated by the user. setdirandgo() will be called if any item in the Listbox is doubleclicked. The Scrollbar is tied to the Listbox by calling the Scrollbar.config() method.

Lines 32–35

We then create a text Entry field for the user to enter the name of the directory he or she wants to traverse to and see its files listed in the Listbox. We add a RETURN or Enter key binding to this text entry field so that the user can hit RETURN as an alternative to pressing a button. The same applies for the mouse binding we saw above in the Listbox. When the user doubleclicks on a Listbox item, it has the same effect as the user's entering the directory name manually into the text Entry field and pressing the “go” button.

Lines 37–54

We then define a Button frame (bfm) to hold our three buttons, a “clear” button (clr), “go” button (ls), and a “quit” button (quit). Each button has its own different configuration and callbacks, if pressed.

Lines 56–58

The final part of the constructor initializes the GUI program, starting with the current working directory.

Lines 60–61

The clrDir() method clears the cwd Tk string variable, which contains the current directory which is “active.” This variable is used to keep track of what directory we are in and, more importantly, helps keep track of the previous directory in case errors arise. You will notice the ev variables in the callback functions with a default value of None. Any such values would be passed in by the windowing system. They may or may not be used in your callback.

Lines 63–71

The setDirAndGo() method sets the directory to traverse to and issues the call to the method that makes it all happen, doLS().

Lines 73–108

doLS() is, by far, the key to this entire GUI application. It performs all the safety checks (e.g., is the destination a directory and does it exist?). If there is an error, the last directory is reset to be the current directory. If all goes well, it calls os.listdir() to get the actual set of files and replaces the listing in the Listbox. While the background work is going on to pull in the new directory's information, the highlighted blue bar becomes a bright red. When the new directory has been installed, it reverts to blue.

Lines 110–115

The last pieces of code in listdir.py represent the main part of the code. main() is executed only if this script is invoked directly, and when main() runs, it creates the GUI application, then calls mainloop() to start the GUI, which is passed control of the application.

We leave all other aspects of the application as an exercise to the reader, recommending that it is easier to view the entire application as a combination of a set of widgets and functionality. If you see the individual pieces clearly, then the entire script will not appear as daunting.

We hope that we have given you a good introduction to GUI programming with Python and Tkinter. Remember that the best way to get familiar with Tkinter programming is by practicing and stealing a few examples! The Python distribution comes with a large number of demonstration applications (see the Demo directory) that you can study. And as we mentioned earlier, there is also an entire text devoted to Tkinter programming.

One final note: do you still doubt the ability of Tkinter to produce a commercial application? Take a close look at IDLE. IDLE itself is a Tkinter application (written by Guido)!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset