Берегите свои переменные!

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

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

В текущей версии tkinter классы переменных обладают деструктором __del__, который автоматически сбрасывает созданную переменную Tk, когда уничтожается объект Python (то есть утилизируется сборщиком мусора). В итоге все ваши переключатели могут оказаться невыбран- ными, если объект переменной будет утилизирован, по крайней мере, до того момента, когда очередной щелчок мышью установит новое значение переменной Tk. В примере 8.29 демонстрируется ситуация, в которой это может случиться.

Пример 8.29. PP4E\Gui\Tour\demo-radio-clear.py

#  берегите переменные переключателей (о чем действительно легко можно забыть)

from tkinter import * root = Tk()

def radio1(): # локальные переменные являются временными

#global tmp # сделав их глобальными, вы решите проблему tmp = IntVar()

for i in range(10):

rad = Radiobutton(root, text=str(i), value=i, variable=tmp) rad.pack(side=LEFT)

tmp.set(5) # выбрать 6-й переключатель

radio1()

root.mainloop()

Кажется, что первоначально должен быть выбран переключатель «5», но этого не происходит. Локальная переменная tmp уничтожается при выходе из функции, переменная Tk сбрасывается и значение 5 теряется (все переключатели оказываются невыбранными). Тем не менее эти переключатели прекрасно работают, если попробовать выполнять на них щелчки мышью, поскольку при этом переменная Tk переустанавливается. Если раскомментировать инструкцию global, кнопка 5 будет появляться в выбранном состоянии, как и задумывалось.

Однако в версии Python 3.X это явление, похоже, приобрело дополнительные отрицательные черты: в этой версии переключатель «5» не только не выбирается изначально, но и перемещение указателя мыши над невыбранными переключателями порождает эффект незаказан- ного выбора многих их них, пока не будет выполнен щелчок мышью. (В версии 3.X также требуется инициализировать строковую переменную StringVar, совместно используемую переключателями, как мы делали это в предыдущих примерах; в противном случае переменная получит пустую строку, как значение по умолчанию, что переведет все переключатели в выбранное состояние!)

Конечно, это нетипичный пример — в таком виде невозможно узнать, какая кнопка нажата, потому что переменная не сохраняется (и параметр command не установлен). Довольно бессмысленно использовать группу переключателей, если позднее нельзя получить значение выбора. Фактически это настолько невразумительно, что я отсылаю вас к примеру demoradioclear2.py в пакете примеров для книги, в котором делается попытка другими способами заставить проявиться эту странность. Возможно, вам это не понадобится, но если вы столкнетесь с этим, не говорите, что я вас не предупреждал.

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

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