[Tkinter-discuss] BooleanVar() etc.

Michael Lange klappnase at web.de
Sun Jun 24 19:44:42 CEST 2012


Hi Mark,

Thus spoketh Mark Summerfield <list at qtrac.plus.com> 
unto us on Sun, 24 Jun 2012 08:42:33 +0100:

> Hi,
> 
> Right now it is possible to do
> 
>     bv = BooleanVar()
>     bv.set(any_old_rubbish)
>     b = bv.get() # b is an int not a bool
> 
> I've reported this as a bug and commented that I think that BooleanVar,
> IntVar, FloatVar, and StringVar should honor the type in their names
> (i.e., bool, int, float, str).
> 
> If this matters to you could you look at the issue and maybe comment?
> 
> http://bugs.python.org/issue15133

I've been there and spent my 2 cents ;)
Now I just wanted to leave a comment here, too.
First, the return value of get() is not neccessarily an int:

>>> b = BooleanVar()
>>> b.set('yes')
>>> b.get()
True
>>> b.set('1')
>>> b.get()
True
>>> b.set(1)
>>> b.get()
1
>>> b.set(True)
>>> b.get()
1
>>> b.set('true')
>>> b.get()
True

At the first glance this seems somewhat erratic, nevertheless there is an
obvious pattern: apparently all the strings that tcl accepts as boolean
values cause get() to return True / False whereas the special values
True / False / 0 / 1 passed to set() cause get() to return 1 / 0.
This might be considered a bug, but it is not a BooleanVar speciality,
but the behavior of tkapp.getboolean() and we encounter it everywhere in
tkinter.

The fact that values like 'yes' are accepted as boolean values does not
seem to make sense if you think of the BooleanVar as a *Python* boolean
object, but if you think of it as a Python representation of a *Tcl*
boolean it makes a lot of sense. 

Then, your above observation that you can pass "any_old_rubbish" to set()
and get() will in return give you an integer is not exactly correct:

>>> b.set(1.5)
>>> b.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.1/tkinter/__init__.py", line 316, in get
    return self._tk.getboolean(self._tk.globalgetvar(self._name))
TypeError: must be string, not float
>>> b.set([])
>>> b.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.1/tkinter/__init__.py", line 316, in get
    return self._tk.getboolean(self._tk.globalgetvar(self._name))
_tkinter.TclError: expected boolean value but got "[]"

and so on.
I agree that it seems odd that you need to call get() to see the error.
OTOH, the special thing about the BooleanVariable is that get() will
always return a boolean (at least if we accept 0 / 1 as bool), no one
promised that set () only accepts bool values:

>>> b.set.__doc__
'Set the variable to VALUE.'
>>> b.get.__doc__
'Return the value of the variable as a bool.'
>>> b.__doc__
'Value holder for boolean variables.'
>>> 

The problem with set() is of course, that it must accept anything that
Tcl might use as boolean, otherwise we might run into trouble if
somewhere the return value of some tcl command is directly passed to
set() .

I think if we do not consider the BooleanVar to be a Python boolean
object but rather a convenience object for handling Tcl boolean values
these limitations won't hurt too much. In fact I have been using
BooleanVars for many years now, and they worked so well that I never even
noticed these oddities.

Regards

Michael

.-.. .. ...- .   .-.. --- -. --.   .- -. -..   .--. .-. --- ... .--. . .-.

War is never imperative.
		-- McCoy, "Balance of Terror", stardate 1709.2


More information about the Tkinter-discuss mailing list