0

I’m struggling with defining checkbuttons in a loop. Below, I have written a very simplified representation of my actual code with 2 versions. Version 1 works fine. However version 2 (with the loop), which I would like to use in my project, does not work. It only works for the last item in the row. I do not understand why this is as checking the values of the varlist reveals that the IntVars in it are defined and set, see the comment ‘# CHECKING’. I also tried a version with a dictionary of IntVars, but that didn’t work neither. I hope somebody can explain what is wrong with version 2. Many thanks.

import tkinter as tk

def state(var):
   if var.get():
      val = var.get()
      print(val)

root = tk.Tk()

# VERSION 1
var1, var2, var3, var4 = tk.IntVar(), tk.IntVar(), tk.IntVar(), tk.IntVar()
var5, var6, var7, var8 = tk.IntVar(), tk.IntVar(), tk.IntVar(), tk.IntVar()
var1.set(0), var2.set(0), var3.set(0), var4.set(0)
var5.set(0), var6.set(0), var7.set(0), var8.set(0)

tk.Label(root, text = 'Version 1, Choose:').pack()
tk.Checkbutton(root, text = 'item1', variable = var1, command = lambda: state(var1)).pack()
tk.Checkbutton(root, text = 'item2', variable = var2, command = lambda: state(var2)).pack()
tk.Checkbutton(root, text = 'item3', variable = var3, command = lambda: state(var3)).pack()
tk.Checkbutton(root, text = 'item4', variable = var4, command = lambda: state(var4)).pack()
tk.Checkbutton(root, text = 'item5', variable = var5, command = lambda: state(var5)).pack()
tk.Checkbutton(root, text = 'item6', variable = var6, command = lambda: state(var6)).pack()
tk.Checkbutton(root, text = 'item7', variable = var7, command = lambda: state(var7)).pack()
tk.Checkbutton(root, text = 'item8', variable = var8, command = lambda: state(var8)).pack()

# VERSION 2
tk.Label(root, text = '').pack()
tk.Label(root, text = 'Version 2, Choose:').pack()
varlist =[]
itemlist = ['item1','item2','item3','item4', 'item5','item6','item7','item8']
for item in itemlist:
   var = tk.IntVar()
   var.set(0)
   varlist.append(var)   
   tk.Checkbutton(root, text = item, variable = var, command = lambda: state(var)).pack()
   print(var, var.get()) # CHECKING     
root.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
Sjaak
  • 53
  • 1
  • 7
  • 1
    #CHECKING does the check when the loop is run. So the initial values(0) are shown. Though you can change `command = lambda var=var: state(var)`, so the corresponding variable is passed on. – Delrius Euphoria Jan 27 '21 at 17:46
  • Cook Cloud many thanks. Yes, this works. And also when I add ‘item=item’ to the lambda expression and ‘item’ to the arguments of the state function call (so that the state function can do something with the checkbutton event). However I do not understand yet the logics as var= var seems to me a tautology, while ‘lambda var: stat(var)’ doesn’t work. Perhaps someone can give me a hint? – Sjaak Jan 27 '21 at 21:14
  • 1
    Its just the way how `lambda` works, it creates a new function where the `var` is `var` that you specify(`var=var`), and then you pass in that `var`. To understand better, you will have to change the arguments here, `command = lambda var_loop=var: state(var_loop)`. – Delrius Euphoria Jan 27 '21 at 23:56

0 Answers0