Introduction

In this tutorial you will learn to

  • understand the original Tk classes
  • redefine them into more powerful classes
  • master object-oriented programming

Our first program

It is somewhat of a tradition for programming tutorials to start with a program which writes hello world to the computer screen. Here is the result of this standard initiation ritual:

../_images/intro1.png

So how do we do this ? First we have to import the module tkinter (Tk interface) and give it the shortcut tk:

import tkinter as tk

Then we create the root widget with class tk.Tk which becomes the root for all other widgets:

root = tk.Tk()

Then we create a label widget with class tk.Label which has root as parent and hello world as text attribute:

label = tk.Label(root, text='hello world!', font='Arial 24')

Then we have to call a placement method such as grid(), to make the label appear inside the window:

label.grid()

Finally we call the main loop method tk.mainloop() which runs continually until the window close button is clicked or the quit Python menu is chosen:

root.mainloop()

This method call is usully the last one in the program, after all the graphical elements and callback functions have been defined.

intro1.py

import tkinter as tk

root = tk.Tk()
label = tk.Label(master=root, text='hello world!', font='Arial 24')
label.grid()
root.mainloop()

The same in OOP

Now we rewrite this first program in OOP manner. We start by defining the new App class:

class App:

This class has two methods:

  • the constructor method __init__()
  • the main loop method run()

The constructor method creates the instance attributes self.root and self.label. It then calls the placement method on the label object:

def __init__(self):
    self.root = tk.Tk()
    self.label = tk.Label(self.root, text='hello world!', font='Arial 24')
    self.label.grid()

In case we do not need to keep a reference to the label object, we can shorten the last two lines to:

tk.Label(self.root, text='hello world!', font='Arial 24').grid()

The run method starts the main loop:

def run(self):
    """Run the main loop."""
    self.root.mainloop()

Finally we instantiate the App and run it:

App().run()

This is the result:

../_images/intro1.png
import tkinter as tk

class App:
    """Define the application class."""
    def __init__(self):

        self.root = tk.Tk()
        self.label = tk.Label(self.root, text='hello world!', font='Arial 24')
        self.label.grid()

    def run(self):
        """Run the main loop."""
        self.root.mainloop()

App().run()

intro2.py

Classic and themed widgets

The elements of a graphical user interface are called widgets. In Tk there are two generations of widgets:

  • the old classic tk widgets, originally introduced in 1991
  • the new themed ttk widgets, added in 2007 with version 8.5

The new themed widgets can be found in the submodule tkinter.ttk. Whenever a newer themed widget is available, we will use it. We import the classic and the new themed widgets with this import statement:

import tkinter as tk
import tkinter.ttk as ttk

This code creates a classic label and a new themed label:

tk.Label(self.root, text='tk.Label').pack()
ttk.Label(self.root, text='ttk.Label').pack()

This code creates a classic button and a new themed button:

tk.Button(self.root, text='tk.Button').pack()
ttk.Button(self.root, text='ttk.Button').pack()

The screen capture below shows the difference in appearance. The new themed widgets (ttk) have a gray background and the buttons have uniform size.

../_images/intro3.png
import tkinter as tk
import tkinter.ttk as ttk

class App:
    """Define the application class."""
    def __init__(self):
        self.root = tk.Tk()
        self.root.title('App')

        tk.Label(self.root, text='old classic tk.Label').grid()
        ttk.Label(self.root, text='new themed ttk.Label').grid()

        tk.Button(self.root, text='tk.Button').grid()
        ttk.Button(self.root, text='ttk.Button').grid()

    def run(self):
        """Run the main loop."""
        self.root.mainloop()

App().run()

intro3.py

Setting options

Options can be set in three ways:

  • at object creation, using keyword arguments
  • after object creation, using a dictionary index
  • use the config() method with keyword attributes
# setting options
import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
ttk.Button(root, text='Set options at creation').grid()

button = ttk.Button(root)
button['text'] = 'Set options as dict'
button.grid()

button = ttk.Button(root)
button.config(text='Set options with config() method')
button.grid()

options = button.config()
for x in options:
    print(x, options[x])

print(button.keys())

root.mainloop()

intro4.py

Let’s define our own widget class

We are now going to redefine the original tk and ttk classes to make our own Tk widget classes. This new classes have the following advantages:

  • the text option has a default value (Label, Button, etc.)
  • the parent object is automatically set (root)
  • all keyword arguments are passed on (kwargs)
  • the themed version is used when available (ttk)

This is our new Label class based on the original themed class:

class Label(ttk.Label):
    """Create a Label object."""
    def __init__(self, text='Label', **kwargs):
        super().__init__(App.stack[-1], text=text, **kwargs)
        self.grid()

This is the new Button class:

class Button(ttk.Button):
    """Create a Button object."""
    def __init__(self, text='Button', **kwargs):
        super().__init__(App.stack[-1], text=text, **kwargs)
        self.grid()

Button

Buttons can be clicked and are used to execute a command associated with them. The following demo creates 4 buttons.

../_images/intro5.png
  • The Start button prints Start to the console
  • The Stop button prints Stop to the console
  • The Self button prints the button object string to the console
  • The Destroy button removes the button from the window
from tklib import *
app = App('Buttons')

Button('Start', 'print("Start")')
Button('Stop', 'print("Stop")')
Button('Self', 'print(self)')
Button('Destroy', 'self.destroy()')
    
app.run()

intro5.py

Radiobutton

Radiobuttons are active elements which can be clicked and execute actions. Only one button is active at any one time.

../_images/intro6.png
from tklib import *
app = App('Radio buttons')

Label('Select your favorite programming language')
Radiobutton('Python;Perl;Ruby;Java;C++', 'print(self.item)')

app.run()

intro6.py

Checkbutton

Checkbuttons are active elements which can be clicked and execute actions. Multiple checkbuttons can be selected simultaneously.

../_images/intro7.png
from tklib import *
app = App('Checkbuttons')

Label('Select your favorite languages')
Checkbutton('Python;Perl;Ruby;Java;C++', 'print(self.selection)')

app.run()

intro7.py

Entry field

Entry entry field presents the user with a single line text field where he can enter a string value.

../_images/intro8.png
from tklib import *
app = App('Entry fields')

Entry('First name:', 'print(self.var.get())')
Entry('Last name:', 'print(self.var.get())')
Entry('Password:', 'print(self.var.get())', show='*')

Entry('Enter expression', 'App.res["text"] = eval(self.var.get())')
App.res = Label('Result')
app.run()

intro8.py

The tklib module

In the following section we are going to redefine the tk and ttk objects. To make it easier to use them, we follow these design principles:

  • we keep the excact same class names
  • the parent object is chosen automatically
  • all keyword arguments are forwarded

The first widget to consider is the Label which just places static text. Where it makes sense, a label will be combined with a button or entry widget.

There are three types of buttons:

  • Button
  • Checkbutton
  • Radiobutton

There are four types of entry widgets for text or numbers, which allow to input text with the keyboard or making a choice uint the mouse:

  • Entry
  • Combobox
  • Spinbox
  • Scale

Then there are the two complex display widgets for text and graphics:

  • Text
  • Canvas

These two widgets present lists:

  • Listbox
  • Treeview

Finally these widgets are helper widgets:

  • Frame
  • Separator
  • Window
  • Scrollbar
  • SizeGrip
  • Progressbar
  • Menu
  • ContextMenu
  • Panedwindow