Виджет Radiobutton (радиокнопка) в Tkinter

В Tkinter от класса Radiobutton создаются радиокнопки. Их не создают по одной, а делают связанную группу, работающую по принципу переключателей. Когда включена одна, другие выключены. В группе радиокнопок нельзя сделать множественный выбор.

Если мы создадим две радиокнопки без соответствующих настроек, то обе они будут включены и выключить их будет невозможно:

Эти переключатели никак не связаны друг с другом. Кроме того для них не указано исходное значение, должны ли они быть в состоянии "вкл" или "выкл". По-умолчанию они включены.

Связь устанавливается через общую переменную Tkinter, разные значения которой соответствуют включению разных радиокнопок группы. У всех кнопок одной группы свойство variable устанавливается в одно и то же значение – связанную с группой переменную. А свойству value присваиваются разные значения этой переменной.

from tkinter import *
root = Tk()
 
r_var = BooleanVar()
r_var.set(False)
r1 = Radiobutton(text='First', variable=r_var, value=False)
r2 = Radiobutton(text='Second', variable=r_var, value=True)
 
r1.pack(anchor=W)
r2.pack(anchor=W)
root.mainloop()

Здесь переменной r_var присваивается объект типа BooleanVar. С помощью метода set он устанавливается в значение False.

При запуске программы включенной окажется первая радиокнопка, так как значение ее опции value совпадает с текущим значением переменной r_var. Если кликнуть по второй радиокнопке, то она включится, а первая выключится. При этом значение r_var станет равным True.

В программном коде обычно требуется "снять" данные о том, какая из двух кнопок включена. Делается это с помощью метода get экземпляров переменных Tkinter.

from tkinter import *

def change():
    match var.get():
        case 0: label['bg'] = 'red'
        case 1: label['bg'] = 'green'
        case 2: label['bg'] = 'blue'

root = Tk()

var = IntVar()
var.set(0)
red = Radiobutton(text='Красная', variable=var, value=0)
green = Radiobutton(text='Зеленая', variable=var, value=1)
blue = Radiobutton(text='Синяя', variable=var, value=2)

button = Button(text='Изменить', command=change)
label = Label(width=20, height=5)

red.pack(anchor=W)
green.pack(anchor=W)
blue.pack(anchor=W)
button.pack(pady=10)
label.pack()
root.mainloop()

В функции change в зависимости от считанного значения переменной var ход выполнения программы идет по одной из трех веток.

Мы можем избавиться от кнопки "Изменить", связав функцию change или любую другую со свойством command радиокнопок. Тогда метка будет менять цвет при клике по радиокнопкам. При этом не обязательно, чтобы радиокнопки, объединенные в одну группу, вызывали одну и ту же функцию.

from tkinter import *

def red_label():
    label['bg'] = 'red'

def green_label():
    label['bg'] = 'green'

def blue_label():
    label['bg'] = 'blue'

root = Tk()

var = IntVar()
var.set(0)
Radiobutton(text='Red', command=red_label,
            variable=var, value=0).pack()
Radiobutton(text='Green', command=green_label,
            variable=var, value=1).pack()
Radiobutton(text='Blue', command=blue_label,
            variable=var, value=2).pack()
label = Label(width=20, height=5, bg='red')
label.pack()

root.mainloop()

Однако, так как код функций почти одинаков, правильнее использовать одну функцию с параметром, а опции command присваивать лямбда-выражение, чтобы иметь возможность передать для него аргумент.

from tkinter import *

def paint(color):
    label['bg'] = color

root = Tk()
var = IntVar()
var.set(0)
Radiobutton(text='Red', command=lambda: paint('red'),
            variable=var, value=0).pack()
Radiobutton(text='Green', command=lambda: paint('green'),
            variable=var, value=1).pack()
Radiobutton(text='Blue', command=lambda: paint('blue'),
            variable=var, value=2).pack()
label = Label(width=20, height=5, bg='red')
label.pack()
root.mainloop()

Если учесть, что радиокнопки однотипны, еще более правильным будет создать класс.

from tkinter import *

class RBColor:
    def __init__(self, color, val):
        self.rb = Radiobutton(text=color.capitalize(),
                              variable=var, value=val,
                              command=self.paint)
        self.rb.pack(anchor=W)
        self.color = color

    def paint(self):
        label['bg'] = self.color


root = Tk()
colors = {0: 'red', 1: 'green', 2: 'blue'}
var = IntVar()
for k, v in colors.items():
    RBColor(v, k)
label = Label(width=20, height=5, bg=colors[0])
label.pack(pady=10)
root.mainloop()

Здесь мы используем словарь, в котором ключи выполняют роль значений для переменной Tkinter.

В последних вариациях кода мы не используем метод get, чтобы получить значение переменной var. В данном случае нам это не требуется, потому что цвет метки меняется в момент клика по соответствующей радиокнопке и не находится в зависимости от значения переменной. Несмотря на это использовать переменную в настройках радиокнопок необходимо, так как она обеспечивает связывание их в единую группу и выключение одной при включении другой.

Практическая работа

Виджеты Radiobutton поддерживают большинство свойств оформления внешнего вида, которые есть у других элементов графического интерфейса. При этом у Radiobutton есть особое свойство indicatoron. По-умолчанию он равен единице (в новых версиях – True), в этом случае радиокнопка выглядит как нормальная радиокнопка. Однако если присвоить этой опции ноль (False), то виджет Radiobutton становится похожим на обычную кнопку по внешнему виду. Но не по смыслу.

Напишите программу, в которой имеется несколько объединенных в группу радиокнопок, индикатор которых выключен (indicatoron=False). Если какая-нибудь кнопка включается, то в метке должна отображаться соответствующая ей информация. Обычных кнопок в окне быть не должно.

Tkinter. Программирование GUI на Python




Все разделы сайта