Флажки и переменные

flazhki i peremennye Экскурсия по tkinter, часть 1

Когда я впервые изучал этот виджет, моей первой реакцией было: «Зачем вообще здесь нужны переменные tkinter, если можно зарегистрировать обработчики щелчков на виджетах?» На первый взгляд связанные переменные могут показаться излишними, но они упрощают некоторые действия с графическим интерфейсом. Не буду просить принять это на веру, а постараюсь объяснить, почему.

Имейте в виду, что обработчик для флажка, указанный в параметре command, будет выполняться при каждом щелчке — при переключении и в выбранное, и в невыбранное состояние. Поэтому если нужно совершить действие немедленно после щелчка на флажке, как правило, в обработчике события требуется узнать текущее значение флажка. Поскольку у флажка нет метода «get», с помощью которого можно было бы получить текущее его значение, обычно требуется запрашивать ассоциированную переменную, чтобы узнать, включен флажок или выключен.

Кроме того, в некоторых графических интерфейсах пользователям разрешается устанавливать флажки без вызова обработчиков, зарегистрированных с помощью параметра command, и получать значения где-либо позже в программе. В таком сценарии переменные служат для автоматического запоминания состояний флажков. Представителем этого последнего подхода является метод report в сценарии demoCheck.

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

Пример 8.23. PP4E\Gui\Tour\demo-check-manual.py

#  флажки, сложный способ (без переменных)

from tkinter import *

states = [] # изменение объекта — не имени

def onPress(i): # сохраняет состояния

states[i] = not states[i] # изменяет False->True, True->False

root = Tk()

for i in range(10):

chk = Checkbutton(root, text=str(i), command=(lambda i=i: onPress(i)) ) chk.pack(side=LEFT)

states.append(False)

root.mainloop()

print(states) # при выходе вывести все состояния

Здесь lambda-выражение передает индекс нажатой кнопки в списке states. Иначе для каждой кнопки потребовалось бы создавать отдельный обработчик. Здесь мы снова вынуждены использовать аргумент со значением по умолчанию, чтобы передать переменную цикла lambda-выражению. В противном случае все 10 сгенерированных функций получили бы значение переменной цикла, присвоенное ей в последней итерации цикла (щелчок на любом флажке изменял бы состояние десятого элемента в списке — причины такого поведения описываются в главе 7). При запуске этот сценарий создает окно с 10 флажками, как показано на рис. 8.27.

Рис. 8.27. Окно флажков с изменением состояний, производимым вручную

 

Состояния флажков, поддерживаемые вручную, обновляются при каждом щелчке на флажках и выводятся при выходе из программы (формально, при возврате из вызова mainloop) — это список логических значений, которые можно было бы представить целыми числами 1 и 0, если бы потребовалось в точности имитировать оригинал:

C:\\PP4E\Gui\Tour> python demo-check-manual.py

[False, False, True, False, True, False, False, False, True, False]

Такой способ действует, и его не столь уж трудно реализовать. Но связанные переменные tkinter заметно упрощают эту задачу, особенно если до какого-то момента в будущем нет необходимости проверять состояния флажков. Это проиллюстрировано в примере 8.24.

Пример 8.24. PP4E\Gui\Tour\democheckauto.py

#  проверка состояния флажков, простой способ

from tkinter import *

root = Tk() states = [] for i in range(10): var = IntVar() chk = Checkbutton(root, text=str(i), variable=var) chk.pack(side=LEFT) states.append(var)

root.mainloop() # пусть следит библиотека tkinter

print([var.get() for var in states]) # вывести все состояния при выходе

#  (можно также реализовать с помощью

#  функции map и lambda-выражение)

Этот сценарий выводит такое же окно и действует точно так же, но здесь мы не передаем обработчики в параметре command, потому что библиотека tkinter автоматически отслеживает изменение состояний:

C:\\PP4E\Gui\Tour> python demo-check-auto.py [0, 0, 1, 1, 0, 0, 1, 0, 0, 1]

Смысл здесь в том, что необязательно связывать переменные с флажками, но если сделать это, то работать с графическим интерфейсом будет проще. Между прочим, генератор списков в самом конце этого сценария является эквивалентом следующим вызовам функции map со связанным методом или lambda-выражением в качестве аргумента:

print(list(map(IntVar.get, states)))

print(list(map(lambda var: var.get(), states)))

Хотя генераторы списков получили большое распространение в настоящее время, тем не менее то, какая форма наиболее понятна вам, может заметно зависеть от вашего… размера обуви.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий