0

For some reason, my code for a Checkbutton variable does not change work when it is inside of a function, however, it works when outside of a function and in its own script. Here is the code for outside a function

from tkinter import *

basket = ['apple','banana','orange']
win2 = Tk()
buttons = []
variables = []
for fruit in basket:
    variable = BooleanVar()
    checkbutton = Checkbutton(win2, text = fruit,variable = variable).pack()
    variables.append(variable)
    buttons.append(checkbutton)
Button(win2, text='Quit', command=win2.destroy).pack()
Button(win2, text='Peek', command=allstates).pack()
mainloop()

Here is the code when defined inside of a function

from tkinter import *
def selectfruit():
    def allstates(): 
        for variable in variables:
            print(variable.get())
    basket = ['apple','banana','orange']
    win2 = Tk()
    print(stls)
    buttons = []
    variables = []
    for fruit in basket:
        variable = BooleanVar()
        checkbutton = Checkbutton(win2, text = fruit,variable = variable).pack(side = TOP)
        variables.append(variable)
        buttons.append(checkbutton)
    Button(win2, text='Quit', command=win2.destroy).pack()
    Button(win2, text='Peek', command=allstates).pack()

For the top bit of code, when I check a box the variables go to True. For the bottom one, they stay at False regardless of what I do.

  • 2
    `win2 = Tk()` is worrying - does this mean that you've called `Tk()` elsewhere in the program? That causes variables to not work - among numerous other problems. Use `Toplevel()` to create additional windows. – jasonharper Aug 10 '20 at 16:06
  • after @jasonharper suggestion, why dont you try changing `variable = BooleanVar()` to `var1 = BooleanVar()` or something, the argument name and variable name are same, might cause some confusion – Delrius Euphoria Aug 10 '20 at 16:11
  • @jasonharper Yeah I have been using multiple windows in this program. I switched it to Toplevel instead of a Tk() and it worked. Could you explain why multiple windows cause issues in the program? I thought it would be fine since they are separate classes – Jeffrey Aug 10 '20 at 16:31
  • Calling `Tk()` does more than just give you a window - it creates an entirely independent GUI environment. Variables, images, etc. created in one environment simply are not accessible to widgets in a different environment. – jasonharper Aug 10 '20 at 16:35
  • I see. Thank you very much! – Jeffrey Aug 10 '20 at 16:44

1 Answers1

0

Give a proper master/parent to your BooleanVar:

variable = BooleanVar(win2)

If I'm not mistaken, not setting master/parent explicitly,
automatically makes it a child of an implicitly-created global root
(like writing root = Tk() at global scope, and using that as parent).
(In your case, if you had created win2 at global scope previously,
then that would be implicitly used - see examples below.)

So your code works, when outside your function,
because BooleanVar and CheckButton happen to have the same Tk/root.

When you put your code inside your function,
BooleanVar and CheckButton get different Tks/roots.
(BooleanVar gets the (perhaps implicitly-created) global root,
CheckButton gets the new win2, that you create inside the function)

Edit/Clarification:
But yes, using Toplevel is probably the correct option.
Just noting what the original issue was;
and it can & does work with multiple Tk widgets.


Examples of the automatic parenting, when parent is omitted
(copied directly from the interactive interpreter):

Not specifying parent/master (here, for the Label widgets),
before creating any Tk widgets
==
Implicitly using, an implicitly-created global Tk/root
(this is the window that pops-up, after the first 'Label()')
(Note: the implicitly created global Tk, will differ
from any Tk widgets, that are explicitly created after it)

>>> from tkinter import *
>>> l1 = Label()
>>> l2 = Label()
>>> id(l1.master) == id(l2.master)
True
>>> root = Tk()
>>> id(root) == id(l1.master)
False

Not specifying parent/master (here, for the Label widget),
after having explicitly created a Tk widget
==
Implicitly using, the already existing Tk widget

>>> from tkinter import *
>>> root = Tk()
>>> l = Label()
>>> id(root) == id(l.master)
True