2

I want to create Button and Entry(state=disabled) widgets with a for loop. The number of widgets to be created will be a runtime argument. What I want is that every time I click the button, the corresponding entry will become enabled(state="normal"). The problem in my code is that any button I click, it only affects the last entry widget. Is there anyway to fix this.? Here is my code:

from tkinter import *

class practice:
    def __init__(self,root):
        for w in range(5):
            button=Button(root,text="submit",
                command=lambda:self.enabling(entry1))
            button.grid(row=w,column=0)
            entry1=Entry(root, state="disabled")
            entry1.grid(row=w,column=1)

    def enabling(self,entryy):
        entryy.config(state="normal")

root = Tk()
a = practice(root)
root.mainloop()
0

2 Answers 2

4

Few issues in your code -

  1. You should keep the buttons and entries you are creating and save them in an instance variable, most probably it would be good to store them in a list , then w would be the index for each button/entry in the list.

  2. When you do lambda: something(some_param) - the function value of some_param() is not substituted, till when the function is actually called, and at that time, it is working on the latest value for entry1 , hence the issue. You should not depend on that and rather you should use functools.partial() and send in the index of Button/Entry to enable.

Example -

from tkinter import *
import functools

class practice:
    def __init__(self,root):
        self.button_list = []
        self.entry_list = []
        for w in range(5):
            button = Button(root,text="submit",command=functools.partial(self.enabling, idx=w))
            button.grid(row=w,column=0)
            self.button_list.append(button)
            entry1=Entry(root, state="disabled")
            entry1.grid(row=w,column=1)
            self.entry_list.append(entry1)

    def enabling(self,idx):
            self.entry_list[idx].config(state="normal")


root = Tk()
a = practice(root)

root.mainloop()
Sign up to request clarification or add additional context in comments.

2 Comments

Wow. that answers my problem! Thank you!
@Crstn Please do note that the first point I said (in my answer) is important. Otherwise you would end up in mysterious bugs.
0

Whenever people have problem with a function created with a lambda expression instead of a def statement, I recommend rewriting the code with a def statement until it works right. Here is the simplest fix to your code: it reorders widget creation and binds each entry to a new function as a default arg.

from tkinter import *

class practice:
    def __init__(self,root):
        for w in range(5):
            entry=Entry(root, state="disabled")
            button=Button(root,text="submit",
                command=lambda e=entry:self.enabling(e))
            button.grid(row=w,column=0)
            entry.grid(row=w,column=1)

    def enabling(self,entry):
        entry.config(state="normal")

root = Tk()
a = practice(root)
root.mainloop()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.