Почему Tkinter getvar() возвращает строковые типы для Booleanvar?

#python #tkinter

#python #tkinter

Вопрос:

Tkinter предлагает тип BooleanVar для логических значений, хранящихся в его виджетах. Однако использование метода getvar для именованного BooleanVar возвращает строковый тип. Для меня это не имеет смысла, поскольку получатель BooleanVar должен возвращать логическое значение.

Есть понимание, почему Tkinter создан таким образом?

Вот краткий пример кода, который показывает, что происходит:

 # importing tkinter module 
from tkinter import *
  
# creating Tk() variable 
master = Tk() 
  
# Tkinter variables 
boolvar = BooleanVar(master, name ="bool") 
Checkbutton(master, 
            text="check", 
            variable=boolvar,
            command=lambda: printvar()).grid(row=0, sticky=W)
  
# Setting values of variables 
master.setvar(name ="bool", value = False)
  
# getting values of each variables using getvar() method
def printvar():
    print("Value of BooleanVar()", master.getvar(name ="bool"))
    print("Type of BooleanVar()", type(master.getvar(name ="bool")))
mainloop()
 

Которые создают окно с флажком. Когда флажок установлен, этот вывод выводится на принтер в терминал:

 Value of BooleanVar() 1
Type of BooleanVar() <class 'str'>
Value of BooleanVar() 0
Type of BooleanVar() <class 'str'>
Value of BooleanVar() 1
Type of BooleanVar() <class 'str'>
Value of BooleanVar() 0
Type of BooleanVar() <class 'str'>
 

Конечно, я могу решить эту проблему, проанализировав строку, но это не похоже на элегантный способ поведения включенной библиотеки Python.

Ответ №1:

Здесь происходит несколько интересных вещей.

Во-первых, встроенный интерпретатор Tcl, который является основой Tkinter, не имеет понятия о логических значениях. Он использует значение 0 для представления false и любое другое число для представления true . BoolVar обрабатывает это в своем get методе, преобразуя любую внутреннюю переменную Tcl в либо True или False .

Однако вы не вызываете get метод переменной. Вместо этого вы вызываете getvar , который возвращает необработанное, неконвертированное значение, хранящееся в интерпретаторе tcl.

Еще больше усугубляет проблему, вы неправильно настраиваете Checkbutton . Поскольку вы не определяете параметры onvalue and offvalue , они по умолчанию используют строки «1» и «0».

Если вы правильно установите onvalue and offvalue в True and False и вызовете get метод переменной, а не using getvar , вы получите правильное логическое значение.

Или, если вы хотите использовать getvar , вы должны сделать то, что BoolVar делает, и преобразовать значение в логическое значение, используя внутреннюю функцию tkinter getboolean .

 Checkbutton(..., onvalue=True, offvalue=False)
...
def printvar():
    ...
    value = master.tk.getboolean(master.getvar(name="bool"))
    print(f"value: {value} type of value: {type(value)}")
 

Комментарии:

1. Спасибо за подробное объяснение — мне очень интересно, что флажки по умолчанию имеют строковые значения, но это имеет смысл с остальной частью вашего объяснения.

2. @shimmer_flight: в основе tkinter лежит интерпретатор tcl. Весь язык основан на строках. Хотя он, конечно, поддерживает числа, его мантра гласит: «все есть строка». Когда вы понимаете язык Tcl, совсем не странно, что по умолчанию используется строка.

Ответ №2:

Чтобы получить значение, вы можете использовать саму переменную, а не получать значение master экземпляра.

 # importing tkinter module 
from tkinter import *
  
# creating Tk() variable 
master = Tk() 
  
# Tkinter variables 
boolvar = BooleanVar(master, name ="bool") 
x = Checkbutton(master, 
            text="check", 
            variable=boolvar,
            command=lambda: printvar()).grid(row=0, sticky=W)
  
# Setting values of variables 
master.setvar(name ="bool", value = False)
  
# getting values of each variables using get() method
def printvar():
    print("Value of BooleanVar()", boolvar.get())
    print("Type of BooleanVar()", type(boolvar.get()))
mainloop()
 

Вывод:

 Value of BooleanVar() True
Type of BooleanVar() <class 'bool'>
Value of BooleanVar() False
Type of BooleanVar() <class 'bool'>
 

Таким образом, он показывает тип переменной как boolean .