I'm currently trying to create a GUI to compare files between two different folders and have a rudimentary framework that I'm trying to build off of right now.
I have three frames on the left, right, and bottom of the window with two checkbuttons each. I want to be able to select each checkbutton independently of each other but every time I click on the first checkbutton of any one of the frames, the first checkbutton for the other frames also selects/deselects at the same time.
Why is this the case, and how do I make them work independently from each other? Here's my code for reference:
from tkinter import *
root = Tk()
leftFrame = Frame(root, bg = "#4d94ff")
leftFrame.pack(side = LEFT, fill = BOTH)
rightFrame = Frame(root, bg = "#ff4d4d")
rightFrame.pack(side = RIGHT, fill = BOTH)
bottomFrame = Frame(root, bg = "#5cd65c")
bottomFrame.pack(side = BOTTOM)
check_L1 = Checkbutton(leftFrame, text = "C1", bg = "#4d94ff")
check_L2 = Checkbutton(leftFrame, text = "C2", bg = "#4d94ff")
check_R1 = Checkbutton(rightFrame, text = "C1", bg = "#ff4d4d")
check_R2 = Checkbutton(rightFrame, text = "C2", bg = "#ff4d4d")
checktype1 = Checkbutton(bottomFrame, text = "Check Type 1", bg = "#5cd65c")
checktype2 = Checkbutton(bottomFrame, text = "Check Type 2", bg = "#5cd65c")
check_L1.grid(row = 0)
check_L2.grid(row = 0, column = 1)
check_R1.grid(row = 0)
check_R2.grid(row = 0, column = 1)
checktype1.grid(row = 0)
checktype2.grid(row = 1)
root.mainloop()
You need to specify a unique variable
with each checkbutton.
var_L1 = tk.IntVar()
var_R1 = tk.IntVar()
...
check_L1 = Checkbutton(..., variable=var_L1)
check_R1 = Checkbutton(..., variable=var_R1)
...
Checkbuttons require a variable to be associated with them. You are't explicitly setting a variable so tkinter is creating defaults. Tkinter does this by creating internal variables named after the checkbutton name.
When you create widgets and don't give them names, tkinter will pick default names. The full name includes the names of entire widget hierarchy. So, for example, the internal name for check_L1
is .!frame.!checkbutton'
, the name for check_R1
is .!frame2.!checkbutton
, and the internal name for checktype1
is '.!frame3.!checkbutton'
.
When tkinter creates the default variables for the checkbuttons it uses only the last component of the full name for the variables. Thus, for check_L1
it creates an internal variable named !checkbutton
. The internal variable for check_R1
is also !checkbutton
, as is the internal variable for checktype2
.
Because all of these checkbuttons share the same internal variable, they are linked.
Note: if you are creating a lot of checkboxes in a loop, you can save the reference to each checkbutton in an array. For example:
vars = []
for i in range(x):
vars.append(tk.IntVar())
...
check_L1 = Checkbutton(..., variable=vars[0])
...
print(f"the value of L1 is {vars[0].get()}")