Для чего нужно использовать объект класса BooleanVar вместо обычной переменной типа bool?
Например , я написал очень простую программу на Tkinter . Есть 3 флажка , активируя которые , можно изменять текстовую область . Она отображает , какие флажки нажаты :
from tkinter import *
class Application(Frame) :
"""Простое приложение"""
def __init__(self,master) :
super().__init__(master)
self.grid()
self.create_widgets()
def create_widgets(self) :
"""Создаёт элементы управления"""
self.is_first_checkbox = None # вопрос в этой строчке
Checkbutton(self,
text = "Флажок 1",
variable = self.is_first_checkbox,
command = self.update_text
).grid(row = 2, column = 0, sticky = W)
self.is_second_checkbox = None # вопрос в этой строчке
Checkbutton(self,
text = "Флажок 2",
variable = self.is_second_checkbox,
command = self.update_text
).grid(row = 3, column = 0, sticky = W)
self.is_third_checkbox = None # вопрос в этой строчке
Checkbutton(self,
text = "Флажок 3",
variable = self.is_third_checkbox,
command = self.update_text
).grid(row = 4, column = 0, sticky = W)
self.results_txt = Text(self,width = 40, height = 5, wrap = WORD)
self.results_txt.grid(row = 5, column = 0, columnspan = 3)
def update_text(self) :
"""Обновляет текстовый элемент"""
result = ""
if self.is_first_checkbox :
result += "Первый флажок активирован.\n"
if self.is_second_checkbox :
result += "Второй флажок активирован.\n"
if self.is_third_checkbox :
result += "Третий флажок активирован.\n"
self.results_txt.delete(0.0,END)
self.results_txt.insert(0.0,result)
window = Tk()
window.title("Флажки")
app = Application(window)
window.mainloop()
Результат - флажки активируются , но никаких изменений в текстовой области не происходит . Теперь я переписываю эту программу , заменяя обычные переменные на объекты класса tkinter.BooleanVar :
from tkinter import *
class Application(Frame) :
"""Простое приложение"""
def __init__(self,master) :
super().__init__(master)
self.grid()
self.create_widgets()
def create_widgets(self) :
"""Создаёт элементы управления"""
self.is_first_checkbox = BooleanVar() # вопрос в этой строчке
Checkbutton(self,
text = "Флажок 1",
variable = self.is_first_checkbox,
command = self.update_text
).grid(row = 2, column = 0, sticky = W)
self.is_second_checkbox = BooleanVar() # вопрос в этой строчке
Checkbutton(self,
text = "Флажок 2",
variable = self.is_second_checkbox,
command = self.update_text
).grid(row = 3, column = 0, sticky = W)
self.is_third_checkbox = BooleanVar() # вопрос в этой строчке
Checkbutton(self,
text = "Флажок 3",
variable = self.is_third_checkbox,
command = self.update_text
).grid(row = 4, column = 0, sticky = W)
self.results_txt = Text(self,width = 40, height = 5, wrap = WORD)
self.results_txt.grid(row = 5, column = 0, columnspan = 3)
def update_text(self) :
"""Обновляет текстовый элемент"""
result = ""
if self.is_first_checkbox.get() :
result += "Первый флажок активирован.\n"
if self.is_second_checkbox.get() :
result += "Второй флажок активирован.\n"
if self.is_third_checkbox.get() :
result += "Третий флажок активирован.\n"
self.results_txt.delete(0.0,END)
self.results_txt.insert(0.0,result)
window = Tk()
window.title("Флажки")
app = Application(window)
window.mainloop()
Теперь всё работает корректно . Мой вопрос состоит в следующем : какой смысл в использовании этих объектов вместо обычных переменных , чем они отличаются от переменных , слылающихся на простые логические значения ? Почему переменные в этом случае не работают и не принимают значение автоматически ? И тогда , в каких вообще случаях нужны использовать объекты класса BooleanVar .
Ответы (1 шт):
tkinter.BooleanVar -- это объект Tk и он умеет хранить и отдавать значение, а, например, в self.is_first_checkbox у вас был бы False или True и немного другое -- они не изменяемые, у них нет какого-либо метода для изменения их состояния (типа метода set).
Т.е. виджет Checkbutton умеет менять значение объекта переданного в variable, но для этого нужны изменяемые объекты с определенными атрибутами (set и get).
А чтобы проверка с if self.is_first_checkbox : имела смысл, виджету нужно менять значение самого атрибута объекта, т.е. что-то вроде setattr(self, 'is_first_checkbox', True), а такое он не сможет сделать.
Немного подробнее про объект BooleanVar из tk:
class BooleanVar(Variable):
"""Value holder for boolean variables."""
_default = False
def __init__(self, master=None, value=None, name=None):
"""Construct a boolean variable.
MASTER can be given as master widget.
VALUE is an optional value (defaults to False)
NAME is an optional Tcl name (defaults to PY_VARnum).
If NAME matches an existing variable and VALUE is omitted
then the existing value is retained.
"""
Variable.__init__(self, master, value, name)
def set(self, value):
"""Set the variable to VALUE."""
return self._tk.globalsetvar(self._name, self._tk.getboolean(value))
initialize = set
def get(self):
"""Return the value of the variable as a bool."""
try:
return self._tk.getboolean(self._tk.globalgetvar(self._name))
except TclError:
raise ValueError("invalid literal for getboolean()")
Как видно, у самого объекта есть методы для установки и получения значения через методы set и get. А "подкапотом" этих методов происходит работа с tk, что наталкивает на вывод, что простые типы python не могут заменить объекты tk для работы с tk :)