Radio Button¶
A radiobutton lets you choose among a number of mutually exclusive options. Radiobuttons are used together in a set and are appropriate when the number of choices is fairly small (about 3-5).
A Radiobutton
object has these attributes:
- parent - the parent object
- text - the text label to display
- command - the callback function
- variable - the variable shared among radiobuttons of a set
- value - the specific value of the radiobutton
Standard Radiobutton¶
Let’s make a program which displays 3 radiobuttons to choose a language.
import tkinter as tk
root = tk.Tk()
var = tk.StringVar()
var.set('English')
def cb():
print(var.get())
tk.Radiobutton(root, text='English', variable=var, value='English', command=cb).pack()
tk.Radiobutton(root, text='German', variable=var, value='German', command=cb).pack()
tk.Radiobutton(root, text='French', variable=var, value='French', command=cb).pack()
root.mainloop()
The radiobutton code consists of 7 lines and has a lot of repeated parts.
Using a list¶
A better way would be to use a list. The code still has 7 lines, but when we increase the number of items, the code length remains constant.
import tkinter as tk
root = tk.Tk()
items = ('English', 'German', 'French', 'Italian', 'Spanish')
var = tk.StringVar()
var.set(items[0])
def cb():
print(var.get())
for x in items:
tk.Radiobutton(root, text=x, variable=var, value=x, command=cb).grid()
root.mainloop()
A better Radiobutton class¶
It’s time now to redefine the Radiobutton
class to create everything in just one line:
Radiobutton('English;German;French', 'print(self.item)')
- the items are declared as a semicolon-separated list
- the command is a string to be evaluated in the Radiobutton environment
- the selected value is available in
self.item
- the selection index is available in
self.val
(could be used as a list index)
"""Create radiobuttons."""
from tklib import *
app = App()
Radiobutton('English;German;French', 'print(self.item)')
app.run()
Now let’s see how this class is defined
class Radiobutton:
"""Create a list-based Radiobutton object."""
def __init__(self, items='Radiobutton', cmd='', val=0, **kwargs):
self.items = items.split(';')
self.cmd = cmd
self.val = tk.IntVar()
self.val.set(val)
for i, item in enumerate(self.items):
r = ttk.Radiobutton(App.stack[-1], text=item, variable=self.val,
value=i, command=self.cb, **kwargs)
r.grid(sticky='w')
def cb(self):
"""Evaluate the cmd string in the Radiobutton context."""
self.item = self.items[self.val.get()]
exec(self.cmd)
The item string is split at the semicolon into a regular list.
The shared variable is a IntVar
object.
Each radiobutton has an integer value (0, 1, 2, …).
The callback function finds the selected item by looking up this integer value in the items list.
Let’s look at another exemple. This time we add another language (Italian) and initialize the default button to 2 (French).
from tklib import *
app = App('Radiobuttons')
Radiobutton('English;German;French;Italian', 'print(self.item)', 2)
app.run()
If something goes wrong¶
Let’s see what happens if there are errors in the options.
If there is no items list, there will be a single item called Radiobutton
.
If there is an error in the expression, this message is written to the console:
File "/Users/raphael/GitHub/tk-tutorial/docs/radio/tklib.py", line 238, in cb
exec(self.cmd)
File "<string>", line 1
print(self.item
^
SyntaxError: unexpected EOF while parsing
from tklib import *
app = App('Radiobuttons')
Radiobutton() # no item list
Radiobutton('A;B', 'print(self.item') # error in command
Radiobutton('a;b', 'print(self.item)') # correct
app.run()