Python3.6 tkinter bug

George Trojan - NOAA Federal george.trojan at noaa.gov
Tue Jan 31 18:48:38 EST 2017


On 2017-01-31 18:02, MRAB wrote:

On 2017-01-31 22:34, Christian Gollwitzer wrote:
> >* Am 31.01.17 um 20:18 schrieb George Trojan - NOAA Federal:
> *>>* Selection of button 'A' also selects button 'C'. Same goes for 'B' and 'D'.
> *>>* I noticed that widget names have changed, which likely leads to the cause:
> *>>
> >>>* /usr/local/Python-3.5.1/bin/python3 foo.py
> *>>* .140182648425776.140182647743208
> *>>* .140182648425776.140182647841848
> *>>* .140182648424152.140182648282080
> *>>* .140182648424152.140182648282136
> *>>
> >>>* /usr/local/Python-3.6.0/bin/python3 foo.py
> *>>* .!frame.!checkbutton
> *>>* .!frame.!checkbutton2
> *>>* .!frame2.!checkbutton
> *>>* .!frame2.!checkbutton2
> *>
> >* The widget names look fine to, and the 3.6 naming is way better, because
> *>* it can be used for debugging more easily. The behaviour you describe can
> *>* have two reasons, a) the same widget can be packed twice b) the widgets
> *>* use the same variable. In Tk, a widget does not need an associate
> *>* variable - which can be done by setting the variable to an empty string,
> *>* or by leaving this option off.
> *>
> >* Presumably Python 3.6 passes anything else than an empty string to Tk as
> *>* the -variable option, maybe a mistranslated None? Can't test it myself,
> *>* but in your example you could, for instance, check the output of
> *>* self.call(w, 'configure'), which lists you the Tk side configuration, or
> *>* self.call(w, 'configure', '-variable') to get specifically the bound
> *>* variable.
> *>
> Perhaps someone who knows Tcl and tk can tell me, but I notice that in
> the first example, the second part of the widget names are unique,
> whereas in the second example, the second part of the widget names are
> the reused (both "!checkbutton" and "!checkbutton2" occur twice). Is
> that the cause?
> Do the names need to be:
> .!frame.!checkbutton
> .!frame.!checkbutton2
> .!frame2.!checkbutton3
> .!frame2.!checkbutton4
> ?


Adding dummy variable solves the issue. Following Christian's
suggestion I added code to print Tk variable:

from functools import partial
import tkinter

class GUI(tkinter.Tk):
    def __init__(self):
        tkinter.Tk.__init__(self)
        frame = tkinter.Frame(self)
        for tag in ('A', 'B'):
            w = tkinter.Checkbutton(frame, text=tag, #
variable=tkinter.IntVar(),
                                    command=partial(print, tag))
            w.pack(side='top', padx=10, pady=10)
            print(tag, self.call(w, 'configure', '-variable'))
            print(w)
        frame.pack(side='top')
        frame = tkinter.Frame(self)
        for tag in ('C', 'D'):
            w = tkinter.Checkbutton(frame, text=tag, #
variable=tkinter.IntVar(),
                                    command=partial(print, tag))
            w.pack(side='top', padx=10, pady=10)
            print(tag, self.call(w, 'configure', '-variable'))
            print(w)
        frame.pack(side='top')

gui = GUI()
gui.mainloop()

The output is:

(venv-3.6.0) dilbert at gtrojan> python foo.py
A ('-variable', 'variable', 'Variable', '', <parsedVarName object:
'!checkbutton'>)
.!frame.!checkbutton
B ('-variable', 'variable', 'Variable', '', <parsedVarName object:
'!checkbutton2'>)
.!frame.!checkbutton2
C ('-variable', 'variable', 'Variable', '', <parsedVarName object:
'!checkbutton'>)
.!frame2.!checkbutton
D ('-variable', 'variable', 'Variable', '', <parsedVarName object:
'!checkbutton2'>)
.!frame2.!checkbutton2

It looks like the default name is the last component of widget tree.

When the # sign is removed, the names are unique and the problem disappears:

(venv-3.6.0) dilbert at gtrojan> python foo.py
A ('-variable', 'variable', 'Variable', '', <parsedVarName object: 'PY_VAR0'>)
.!frame.!checkbutton
B ('-variable', 'variable', 'Variable', '', <parsedVarName object: 'PY_VAR1'>)
.!frame.!checkbutton2
C ('-variable', 'variable', 'Variable', '', <parsedVarName object: 'PY_VAR2'>)
.!frame2.!checkbutton
D ('-variable', 'variable', 'Variable', '', <parsedVarName object: 'PY_VAR3'>)
.!frame2.!checkbutton2


More information about the Python-list mailing list