Thursday, July 9, 2009

Tkinter+Ttk Tutorial Part 2: Menu, label, packing and callbacks

Purpose

This article will show you how to structure a Tkinter+Ttk application, add a menu and tie the menu items with commands, one of which will create a Label in the centre of the window.

Difficulty: Moderate
Requirements: Python 3.1+ with tkinter and a little common sense

Building on the last part of the tutorial, this part goes deeper in the subject of GUI programming with tkinter+ttk: it shows how to accomplish something useful. You'll read about how to structure GUI code in pythonic OOP manner, create a menubar and assign or connect commands to the menu entries and create a Label and position it.

Example 1: A window with structured code

This example shows a slightly extended version of the minimal application you could read before. There are three additions and modifications:
  1. The code for the window class in this example will inherit from Frame class and extend it.
  2. The window gets it's file name as title displayed on the title-bar.
  3. It uses the geometry method to adjust the window size.
The results will look similar to the last example, just a little bigger and with a name on the top:



Note: From now on I will strip the comments from the blog version of the code and highlight the currently interesting code parts. The gist version has the comments.

Source code for ttk020.py (gist):
from tkinter.ttk import *

class App(Frame):
def __init__(self):
Frame.__init__(self)
self.master.title(__file__)

self.master.geometry('400x300')
self.pack()

self.mainloop()

if __name__ == '__main__':
App()

The above code does the following things:
  1. Import everything from the ttk module (it is designed so that this does not create conflicts).
  2. Create a class that inherits form the Frame class.
  3. Call parent constructor.
  4. Set the title of the window.
  5. Set the size of the window with the geometry command and tell the window to resize with the pack command.
  6. Run the main loop.
  7. The App class that inherits from the Frame class - our window - is then created when this script is called.
Note: Because I use the __file__ variable to set the title, this script will only work as file script, not on the interactive shell.

Example 2: Adding widgets and callbacks

This example extends the above application with a menu which items are bound to commands and it gets a label. The result will look something like this:



Source code for ttk021.py (gist with comments):
from tkinter import *
from tkinter.ttk import *

class App(Frame):
def __init__(self):
Frame.__init__(self)

self.master.geometry('400x300')
self.master.title(__file__)

self.pack()

self.menu = Menu(tearoff=False)
self.master.config(menu = self.menu)

fm = self.file_menu = None
fm = Menu(self.menu, tearoff=False)
self.menu.add_cascade(label='File', menu = fm)

fm.add_command(label='Say Hello', command = self.say_hello)
fm.add_separator()
fm.add_command(label='Quit', command = self.quit)

self.mainloop()

def say_hello(self, *e):
self.label = Label(self.master, text='Hello there!')
self.label.pack(anchor=CENTER, fill=NONE, expand=YES, side=LEFT)

if __name__ == '__main__':
App()

Explanation of the above code:
  1. The import section now also imports the tkinter module. This is done because the menu is defined there and not in ttk. Including the two modules this way will overwrite any new widgtes over the old and enable the new default theme for the looks.
  2. In the constructor of the App class now creates a menu and assigns it to the window with the config function. The tearoff parameter at creation adapts the looks.
  3. In the next block a cascade is added, which is the File menubar item you can click on to. Then it is assigned to the menu as child so that the application knows where to put it.
  4. The following block adds the "Say Hello", a seperator and the "Quit" menu items to the File menu. The command parameter defines what to do when the menu option is activated (clicked).
  5. The "Say Hello" option will call the say_hello callback method that is declared below the constructor. The "Quit" option will call the inherited quit callback from the Frame class and end the program.
  6. The callback when run creates a new Label with the text "Hello there!" and positions it in the centre of the window. The parameters for the pack method tell it where to place it. Anchor tells to put it in the middle, Fill tells that the Label itself should only use the space it needs and leave the rest alone, Expand tells the align context and side tells where the base point is. You'll see more packing later on.
Epilouge

This post showed how to add some basic widgets to the window and connect commands to menu items that do something. Next post will detail some more widgets and extend the window some more.

1 comment:

  1. Pls, how did you get the pretty frame/bg?
    My py3 just has the ugly old windows system frame.
    THanks...Vernon

    ReplyDelete