1. A Word on Tkinter and GUI Toolkits
Tkinter is a graphic user interface (GUI) toolkit that comes with Python by default. Like wxPython, Tkinter is as cross-platform as Python.
Graphical User Interfaces (GUIs) rely heavily on object-oriented programming. Tkinter is no different. You first instantiate an object and then work with that object's attributes and methods. In this guide, we will complement our guide on wxPython and look at the rudiments of a very simple program that prints "Hello, World!" to a window on your desktop. Tkinter is not as clean as wxPython, so there will be a bit more code to this guide.
2. First the Bang Line
As with all but the simplest Python programs, we start with a bang line:
#!/usr/bin/env python
Naturally, you will need to adapt this to the execution path of your
local file system. Do note that all paths should be absolute, not
local to the directory in which you are executing the program.
3. Importing Tkinter
After the bang line, import all from the Tkinter module:
from Tkinter import *
By using this syntax instead of, say, "import Tkinter", we do not need
to use "Tkinter" as a
namespace.
Nonetheless, this line will import the entire Tkinter module for use.
Next, we need to define the class for our "Hello, World!" program.
4. A Prototypical Greeter
As mentioned previously, graphic user interface (GUI) programming relies heavily on object-oriented principles. In the case of our program, we need to define a class that will then be called by the main function.
We are using the Tkinter toolkit and not recreating it, so we will create an inherited class that relies on Tkinter's Frame class.
class Greeter (Frame):
From there, we will next define functions for each window or frame
that we want our program to create.
5. Me, Myself, and I
Within the Greeter class, we next need to define the __init__ function. It is called __init__ because it is called whenever an object instance of the class is instantiated. Without it, you will have the dream of an object but will never be able to realise it (you won't be able to create one). So let's create the first function of our class as follows (mind any wrap):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
As with most __init__ functions, we here require the argument self to
represent the function itself. By default, all classes derived from
Tkinter's Frame class will look for the master widget to be defined.
Here we tell it has none.
Within the function itself, we then call the Frame class' __init__ class to initiate a frame in memory. Then we pack it and tell Python to create the widgets. The pack method is inherited from Frame and makes the frame visible.
The createWidgets method is defined in the next step and is necessary for the user to do anything with the program. If you want an illustration of a frame without a widget, simply comment out this line when you run the program. Don't worry, it won't go very far.
6. Create Widgets
The next function in the Greeter class is used to create the widgets that populate the frame. The code reads as follows:
def createWidgets(self):
self.QUIT = Button(self)
self.QUIT["text"] = "QUIT"
self.QUIT["fg"] = "red"
self.QUIT["command"] = self.quit
self.QUIT.pack({"side": "left"})
self.Hello = Button(self)
self.Hello["text"] = "Hello",
self.Hello["command"] = self.say_hello
self.Hello.pack({"side": "left"})
Obviously, this function operates solely on the instantiated object of
the Greeter class (as evidenced by the required argument of 'self').
In the course of the above code, two buttons are defined: Quit and
Hello. There is nothing magical in how they are referenced other than
ensuring a sense of order in the program.
Each button is an object of the Button class (part of Tkinter). In the subsequent lines, we define several attributes of each object. The "text" of the button is what the user sees. The "fg" is the colour of the text ("bg" being the obvious complement). The process that should be initiated by the button is then defined by the "command" attribute.
While these three are defined on multiple lines, you could include them all as part of the instantiation of each button. For example, the first button could be instantiated as follows:
self.QUIT = Button(self, text="QUIT", fg="red", command=self.quit)
In either case, the pack method is then invoked again to make it all
visible.
7. Say Hello - Part One
The third and final function in the Greeter class is used to launch a second window from the first and to issue the greeting "Hello, World!". This function further serves to illustrate how to use Tkinter with Python without having to code new classes. It is self-contained - having no outside code save for the Tkinter Greeter object itself.
def say_hello(self):
greet = Tk()
greet.geometry("110x75+350+70")
greeting = Label(greet, text = "Hello, World!")
button = Button(greet, text = "OK", command = greet.quit)
greeting.pack()
button.pack()
greet.mainloop()
Due to the exigencies of space, we analyse this code in the next step of this guide.
8. Say Hello - Part Two
This discussion relies on the code presented in "Say Hello - Part One". If you have not read the beginning of this series, you can begin with "A Word on Tkinter and GUI Toolkits".
The first line of the definition creates an object greet, an instance of the Tk class. We then use Tk's geometry method to declare the precise geometry (110x75 pixels) and location of the frame, using the upper left of the screen for orientation (i.e., 0,0).
In the next two lines, we define the label and the button text for the new window. The label is an instance of the Label class from Tkinter. The first argument is the object to which the label pertains. The second is the attribute, our greeting.
The button similarly is defined according to the prototype Button class of Tkinter. It is then associated with the greet object. The text on the button will simply read "OK". When the button is pressed or clicked, greet's quit method will be called and the frame scrapped.
Both the label and button need to be manifest on the window using the pack method again to do this. Finally, we call the mainloop of greet and the whole package goes into effect.
While that develops the class Greeter, we still have to call it. Next, we need to define the main function, the brains of our program.
9. The main() Thing
As in the say_hello method of Greeter, we need to create a main frame. We here do that in the main() function. We then use that frame for the instance of Greeter and the rest of the program.
def main():
root = Tk()
app = Greeter(master=root)
app.mainloop()
root.destroy()
The object of Greeter is called app. The master of that instance is root, the main frame of the program. After instantiating app, we can then call its mainloop method to run the program. Once all is said and done, the last call of the main() function is to destroy the root window.
10. Calling main()
As usual, the main() function is the brains of the program. But it is worthless unless it is called. Here we call the main() function when the application is invoked directly:
if __name__ == "__main__":
main()
By using this way of coding the program, the window is only created when the program is called directly. If, however, another Python program imports the file as a module, the program does not execute but stays secondary to the invoking application's processes. For more on __name__ and calling main(), see "What's in a Name?"
