|
GUI Programming in Python For Beginners: Create a Timer in 30 Minutes
Saving Absent-Minded Geeks From Soggy Gardens and Burned FoodPython programming is all the rage, because the language has such simple, clean syntax, is easy to learn and has lots of libraries available. But best of all, you're not limited to writing command-line applications. Python has at least four ways to make graphical apps, but today I'll concentrate on one: TkInter. TkInter isn't necessarily the most powerful of the Python windowing packages, but it's well supported on all operating systems. You can give your application to your Windows- and Mac-using friends and they'll be able to run it, as long as they have Python installed. On Linux, though, you may have to install it: on Ubuntu or Debian the package is named python-tk, while in Fedora it's tkinter. For a project, start with a simple one. How about an "eggtimer"? I'm always forgetting that I have cornbread baking in the oven, or that I turned on the sprinklers in the garden. I need something to remind me. Let's start with a very simple Tkinter program. Paste the following into your editor of choice (vim, emacs, kate, leafpad or whatever) and write it to a file named, say, eggtimer: #!/usr/bin/env python from Tkinter import * root = Tk() button = Button(root, text="Hello", command=quit) button.pack() root.mainloop() You can run your script by typing: python eggtimeror, if you make the file executable (see the shell scripting article), you can run it just by typing eggtimer or double-clicking it from your file manager.
(Figure 1, Listing 1.)
Adding controlsOkay, a single button isn't so useful. For a timer, you need to be able to set when it will alert you. And for that, a Scale is a good choice. It gives you a slider you can use to choose how many minutes you want your timer to wait. Add these two lines to your script right before the line where you create your button: scale = Scale(root, from_=1, to=45, orient=HORIZONTAL, length=300) scale.pack()
Of course, Tkinter has other controls (called widgets) besides Scale.
You can also add controls to make things look nicer. For instance, you can add a Label just before you create the Scale, to specify that the slider means a time in minutes: minutes = Label(root, text="Minutes:") minutes.pack(side=LEFT)Figure 3 shows what the window looks like now, and Listing 3 has the code. ====================================================== # Listing 1 #!/usr/bin/env python from Tkinter import * root = Tk() button = Button(root, text="Start timing", command=quit) button.pack(side="left") root.mainloop() ====================================================== ====================================================== # Listing 2 #!/usr/bin/env python from Tkinter import * root = Tk() scale = Scale(root, from_=1, to=45, orient=HORIZONTAL) scale.pack() button = Button(root, text="Start timing", command=quit) button.pack() root.mainloop() ====================================================== ====================================================== # Listing 3 #!/usr/bin/env python from Tkinter import * root = Tk() minutes = Label(root, text="Minutes:") minutes.pack(side=LEFT) scale = Scale(root, from_=1, to=45, orient=HORIZONTAL, length=300) scale.pack() button = Button(root, text="Start timing", command=quit) button.pack() root.mainloop() ======================================================
Packing Them InPacking them in
The
But
Think of your window as a grid, with some number of rows and columns.
Each time you add a new widget, you can specify exactly where in the
grid it goes. For example, try removing all the minutes.grid(row=0, column=0) scale.grid(row=0, column=1) button.grid(row=1, column=1, pady=5, sticky=E) Now the window looks like Figure 4 (Listing 4).
Doing something useful: setting the timerNow you have a nice window ... but it still doesn't do anything yet. How do you make it start a timer when you click Start?
The answer is that
def start_timer() :
root.after(scale.get() * 60000, show_alert)
scale.get() gets the value the user set with the slider.
root.after() sets a timeout -- but it's in milliseconds,
not minutes, so you have to multiply the scale's value by 60,000.
Here's a tip, though: when you're debugging, you might want to use 1000 rather than 60000, so the slider represents seconds, not minutes and you don't have to wait so long to see if your code works.
Now all that's left is the
def show_alert() :
root.bell()
tkMessageBox.showinfo("Ready!", "DING DING DING!")
quit()
====================================================== # Listing 4 #!/usr/bin/env python from Tkinter import * root = Tk() minutes = Label(root, text="Minutes:") minutes.grid(row=0, column=0) scale = Scale(root, from_=1, to=45, orient=HORIZONTAL, length=300) scale.grid(row=0, column=1) button = Button(root, text="Start timing", command=quit) button.grid(row=1, column=1, pady=5, sticky=E) root.mainloop() ======================================================
That's it! You can get more information on Tkinter programming from the links below. Links:Akkana Peck is a freelance programmer and writer and a Python fan; you can find some of her other Python hacks at http://shallowsky.com/software/ She's also the author of Beginning GIMP: From Novice to Professional.
======================================================
# Listing 6
#!/usr/bin/env python
from Tkinter import *
def messageWindow() :
win = Toplevel()
b = Button(win, text='DING DING DING',
bg="blue", fg="yellow",
activebackground="red", activeforeground="white",
padx=root.winfo_screenwidth()/2,
pady=root.winfo_screenheight()/2,
command=quit)
b.pack()
root.mainloop()
def show_alert() :
root.bell()
messageWindow()
quit()
def start_timer() :
root.after(scale.get() * 60000, show_alert)
root = Tk()
minutes = Label(root, text="Minutes:")
minutes.grid(row=0, column=0)
scale = Scale(root, from_=1, to=45, orient=HORIZONTAL, length=300)
scale.grid(row=0, column=1)
button = Button(root, text="Start timer", command=start_timer)
button.grid(row=1, column=1, pady=5, sticky=E)
root.mainloop()
======================================================
|