Search code examples
pythontkinter

Tkinter, Python. When creating slider with a for loop, it got stuck at the last index


when i create a for loop to create 6 sliders in tkinter, and store it's value into a list, the index of the for loop keeps on staying at the last one (number 6) when i control any of the slider.
The values that I stored does change, I guess. However, the index does not, making me cant command it to do other stuff.

Here is my code

import tkinter as tk
from tkinter import ttk
root = tk.TK()
root.geometry('700x700')

Joint_param = {}
Joint_param["J1"] = [0, -120, 120]
Joint_param["J2"] = [10, -70, 90]
Joint_param["J3"] = [20, -120, 60]
Joint_param["J4"] = [30, -90, 90]
Joint_param["J5"] = [40, -140, 140]
Joint_param["J6"] = [50, -180, 180]

slider_value = []
for i in range(6):
    self.slider_value[i].append(tk.DoubleVar())


for i in range(6):
    slider[f'{i+1}'] = ttk.Scale(self.frame_control, from_=Joint_param[f'J{i+1}'][2], to=Joint_param[f'J{i+1}'][1], orient=tk.VERTICAL, variable=slider_value[i], command = lambda x: slider_ctrl(i))

command slider_ctrl:

Here I tried printing the index value to see the problem

def slider_ctrl(index):
    print(index)
    slider_value[index].set(round(float(slider_value[index].get()),2))

Result:

0
1
2
3
4
5
5
5
5
5
5
5

from 0 to 5 is because i print it when it was first created
the others was when i tried changing everyslider


Solution

  • you can pass the current value of i as a default argument in the lambda function, which will freeze the value of i for each iteration. for ex:

    import tkinter as tk
    from tkinter import ttk
    
    root = tk.Tk()
    root.geometry('700x700')
    
    Joint_param = {
        "J1": [0, -120, 120],
        "J2": [10, -70, 90],
        "J3": [20, -120, 60],
        "J4": [30, -90, 90],
        "J5": [40, -140, 140],
        "J6": [50, -180, 180]
    }
    
    # Frame for controls
    frame_control = tk.Frame(root)
    frame_control.pack()
    
    
    # Initialize sliders and values
    slider_value = []
    sliders = []
    
    # Function to handle slider value change
    def slider_ctrl(index):
        print(f"Slider {index + 1} value: {slider_value[index].get()}")
        slider_value[index].set(round(float(slider_value[index].get()), 2))
    
    # Create sliders in a loop
    for i in range(6):
        # Init DoubleVar for each slider
        var = tk.DoubleVar(value=Joint_param[f"J{i + 1}"][0])
        slider_value.append(var)
    
        # create and pack each slider
        slider = ttk.Scale(
            frame_control,
            from_=Joint_param[f'J{i+1}'][2],
            to=Joint_param[f'J{i+1}'][1],
            orient=tk.VERTICAL,
            variable=var,
            command=lambda x, idx=i: slider_ctrl(idx)  # Pass idx as default arg
        )
        slider.grid(row=0, column=i, padx=10)
        sliders.append(slider)
    
    
    root.mainloop()
    
    

    Hope this helps.