Radiobutton и Checkbutton. Переменные Tkinter

В Tkinter от класса Radiobutton создаются радиокнопки, от класса Checkbutton – флажки.

Радиокнопки не создают по одной, а делают связанную группу, работающую по принципу переключателей. Когда включена одна, другие выключены.

Экземпляры Checkbutton также могут быть визуально оформлены в группу, но каждый флажок независим от остальных. Каждый может быть в состоянии "установлен" или "снят", независимо от состояний других флажков. Другими словами, в группе Checkbutton можно сделать множественный выбор, в группе Radiobutton – нет.

Radiobutton – радиокнопка

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

Виджеты радиокнопок

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

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

В Tkinter нельзя использовать любую переменную для хранения состояний виджетов. Для этих целей предусмотрены специальные классы-переменные пакета tkinter – BooleanVar, IntVar, DoubleVar, StringVar. Первый класс позволяет принимать своим экземплярам только булевы значения (0 или 1 и True или False), второй – целые, третий – дробные, четвертый – строковые.

r_var = BooleanVar()
r_var.set(0)
r1 = Radiobutton(text='First', variable=r_var, value=0)
r2 = Radiobutton(text='Second', variable=r_var, value=1)

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

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

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

from tkinter import *
 
def change():
    if var.get() == 0:
        label['bg'] = 'red'
    elif var.get() == 1:
        label['bg'] = 'green'
    elif var.get() == 2:
        label['bg'] = 'blue'
 
root = Tk()
 
var = IntVar()
var.set(0)
red = Radiobutton(text="Red", variable=var, value=0)
green = Radiobutton(text="Green", variable=var, value=1)
blue = Radiobutton(text="Blue", variable=var, value=2)
button = Button(text="Изменить", command=change)
label = Label(width=20, height=10)
red.pack()
green.pack()
blue.pack()
button.pack()
label.pack()
 
root.mainloop()

Метод get()

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

Checkbutton – флажок

Флажки не требуют установки между собой связи, поэтому может возникнуть вопрос, а нужны ли тут переменные Tkinter? Они нужны, чтобы снимать сведения о состоянии флажков. По значению связанной с Checkbutton переменной можно определить, установлен ли флажок или снят, что в свою очередь повлияет на ход выполнения программы.

У каждого флажка должна быть своя переменная Tkinter.

from tkinter import *
root = Tk()
 
cvar1 = BooleanVar()
cvar1.set(0)
c1 = Checkbutton(text="First", variable=cvar1, onvalue=1, offvalue=0)
c1.pack(anchor=W)
 
cvar2 = BooleanVar()
cvar2.set(0)
c2 = Checkbutton(text="Second", variable=cvar2, onvalue=1, offvalue=0)
c2.pack(anchor=W)
 
root.mainloop()

Checkbutton - флажки

С помощью опции onvalue устанавливается значение, которое принимает связанная переменная при включенном флажке. С помощью свойства offvalue – при выключенном. В данном случае оба флажка будут выключены, так как методом set() были установлены соответствующие этому значения.

С помощью методов select() и deselect() флажков можно их программно включать и выключать. То же самое относится к радиокнопкам.

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

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

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

Программа с радиокнопками

Помните, что свойство command есть не только у виджетов класса Button.

Курс с примерами решений практических работ: android-приложение, pdf-версия.

Комментарии

from tkinter import *
root = Tk()
root.title('Program')
f1 = Frame()
f2 = Frame()
 
 
def telephone():
    if var.get() == 0:
        l['text'] = '+7895422411'
    elif var.get() == 1:
        l['text'] = '88005553535'
    elif var.get() == 2:
        l['text'] = '88881481515'
 
 
var = IntVar()
var.set(0)
r1 = Radiobutton(f1, text='Petya', width=5, height=1, indicatoron=0, variable=var, value=0, command=telephone)
r2 = Radiobutton(f1, text='Vasya', width=5, height=1, indicatoron=0, variable=var, value=1,  command=telephone)
r3 = Radiobutton(f1, text='Anna', width=5, height=1, indicatoron=0, variable=var, value=2,  command=telephone)
l = Label(f2, width=10, height=3)
f1.pack(side=LEFT)
r1.pack(anchor=W)
r2.pack(anchor=W)
r3.pack(anchor=W)
f2.pack(side=LEFT)
l.pack()
 
root = mainloop()
Получилось так. Всё работает нормально, оптимизировать можно, и где как лучше можно было бы сделать?

Практическая работа. Выполнила, но криво (кнопки Radiobutton с залипают). Может подскажет кто-нибудь, как исправить?
from tkinter import *
root=Tk()
root.geometry("200x120")
numbers={"Вася":"+375296549875", "Петя":"+375335987654", "Маша":"+3752916451845"}
var=IntVar()
class Radiobut:
    def __init__(self, master, name):
        self.name=name
        self.rb=Radiobutton(master, width=10, height=2, text=self.name, indicatoron=0, command=self.phone) 
        self.rb.pack(side=TOP, fill=X)
    def phone(self):
        l['text']=numbers[self.name]    
l=Label()
l.pack(side=RIGHT, fill=Y)
for n in numbers:
    Radiobut(root, n)   
 
root.mainloop()

Ответ на от AnnaKo

from tkinter import *
root=Tk()
root.geometry("200x120")
numbers={"Вася":"+375296549875", "Петя":"+375335987654", "Маша":"+3752916451845"}
var=IntVar()
class Radiobut:
    def __init__(self, master, name):
        self.name=name
        self.rb=Radiobutton(master,text=self.name, variable=var, width=10, height=2, anchor=W, value=numbers[self.name], indicatoron=0, command=self.phone) 
        self.rb.pack(side=TOP, fill=X)
    def phone(self):
        l['text']=numbers[self.name]    
l=Label(bg="white")
l.pack(side=RIGHT, fill=Y)
for n in numbers:
    Radiobut(root, n)    
root.mainloop()

from tkinter import *
root=Tk()
def phone():
    label['text']=var.get()
var=IntVar()
var.set(0)
Radiobutton(text="Вася", variable=var, value="810375297457365", width=10, height=3,command=phone, indicatoron=0).grid(row=0, column=0, sticky=W)
Radiobutton(text="Петя", variable=var, value="810375299754987", width=10, height=3, command=phone, indicatoron=0).grid(row=1, column=0, sticky=W)
Radiobutton(text="Маша", variable=var, value="810375291645184", width=10, height=3,command=phone, indicatoron=0).grid(row=2, column=0, sticky=W)
label=Label(width=20, heigh=10, bg="white")
label.grid(row=0, column=1, rowspan=3)
root.mainloop()

from tkinter import *
 
#Словарь с данными людей
persons = {
    'Петя': '+4908453325',
    'Вася': '+2908445339',
    'Миша': '+1934453325',
    'Гоша': '+2934453465',
    'Саша': '+6954233644'
}
 
#Установка информации о человеке в label
def get_info():
    label.config(text=persons[var.get()])
 
 
root = Tk()
root.title('Информация о сотруднике')
root.resizable(height=False, width=False)
 
f_left = Frame(root)
f_left.pack(side=LEFT)
 
label = Label(root, justify='center', width=40, text='Выберите сотрудника', font=18)
label.pack(side=LEFT, expand=True)
 
var = StringVar()
 
for name in persons.keys():
    Radiobutton(f_left, width=20, font=20, text=name, indicatoron=0, variable=var, value=name, command=get_info).pack(side=TOP)
 
root.mainloop()
<python/>

from tkinter import *
def a():
    print(cvar1)
 
root = Tk()
 
cvar1 = BooleanVar()
cvar1.set(0)
c1 = Checkbutton(text="First", variable=cvar1, onvalue=1, offvalue=0)
c1.pack(anchor=W)
 
btn= Button(text = 'check', command = a)
btn.pack()
 
root.mainloop()
При запуске печатает только PY_VAR0, независимо от того, включена ли кнопка или нет. С чем связано?

Ответ на от Арсений

cvar1 - это объект типа BooleanVar, а не простой тип данных. Чтобы извлечь из объекта значение, надо использовать метод get(): 

def a():
    print(cvar1.get())

Моя версия) Если кому интересно ;)
from tkinter import *
 
root = Tk()
root.title('Program')
root.geometry("400x200")
class Interface(object):
	def __init__(self, master, obj):
		self.info = obj
		self.main = Frame(master)
		self.menu = Frame(self.main)
		self.wind = Frame(self.main)
		self.l = Label(self.wind, text = "", height = 4, width = 15, bg = "grey", font = ("Roboto", 24, "bold"))
		self.rgroup = StringVar()
		self.r = []
		k = 0
		for i in obj.keys():
			self.r.append(Radiobutton(self.menu, indicator = 0, text = i, variable=self.rgroup, value=i, height = 1, width = 3, command = self.change))
			k +=1
 
		for r in self.r:
			r.pack(side=TOP)
 
		self.l.pack( fill = Y )
		self.menu.pack(side=LEFT)
		self.wind.pack(side=RIGHT)
 
		self.main.pack(expand = 1)
 
	def change(self):
		self.l["text"] = self.info[self.rgroup.get()]
 
Interface(root, {
	"a": ord("a"),
	"b": ord("b"),
	"c": ord("c")
	})
 
root.mainloop()