Hailey
Hailey

Reputation: 11

Tkinter Checkbutton variable

I'm not great at tkinter or even python so I've run into what should be a simple problem.

I have something like this in the middle of my project:

visible = numLevels * [IntVar(value=1)]

top = Toplevel()
settingslabel = Label(top, text='Settings', height=0, width=100)

for i in range(0, numLevels ):
    check = ttk.Checkbutton(settingslabel, text='Level ' + str(i), variable=visible[i])
    check.grid(column = 0, row = i)
    check.var = visible[i]

settingslabel.grid(column = 0, row=0)

I want to have settings screen with a checkbox for every level, while maintaining an array of integers that represent the status of each button.

However, all checkboxes are synchronized. Meaning, when I check a box, all other boxes also become checked. I believe that this is because of the 'variable' field of the checkbutton. As the loop continues, i is updated, and as a result, visible[i] changes as well. I want to preserve the variable when I created the checkbutton. I don't understand how tkinter/python work well enough to know.

The number is levels can be any integer > 0 and is determined at runtime so I can't just unroll the loop.

Is there a better way to do this? Thanks in advance.

Upvotes: 0

Views: 452

Answers (1)

pstatix
pstatix

Reputation: 3858

This is a duplicate of this SO post, but explanation below.

Its because all your boxes are sharing the same tkinter.Intvar() object:

numlevels = 5
visible = numlevels * [IntVar(value = 1)]

for i in range(len(visible)):
    print (hex(id(visible[i]))

# Outputs:
'0x67f8190'
'0x67f8190'
'0x67f8190'
'0x67f8190'
'0x67f8190'

To solve: visible = [IntVar(value = 1) for i in range(numlevels)]

Upvotes: 1

Related Questions