Skip to content
Advertisement

How to generate “n” rows of Entry boxes from another Entry box?

I want to get an integer from an entry field and create new entry boxes below that. I have written a code to do that using a button. However, I want to make it happen automatically without a button as I entered the number, the rows update.

I saw one way to automate it is using the callback.

from tkinter import *

root = Tk()
root.geometry("400x400")

n_para = IntVar()

label1 = Label(root, text="Numeric parameters")
label1.grid(row=0, column=0)

entry1 = Entry(root, textvariable=n_para)
entry1.grid(row=0, column=1)

def update():
    for i in range(1, n_para.get()+1):
        entryX = Entry(root)
        entryX.grid(row=i+1, column=0)

        entryY = Entry(root)
        entryY.grid(row=i+1, column=1)

        entryZ = Entry(root)
        entryZ.grid(row=i+1, column=2)

button1 = Button(root, text="update", command=update)
button1.grid(row=1, column=0)

root.mainloop()

So, I changed the code to the below one using callback.

from tkinter import *

root = Tk()
root.geometry("400x400")

n_para = IntVar()

label1 = Label(root, text="Numeric parameters")
label1.grid(row=0, column=0)

entry1 = Entry(root, textvariable=n_para)
entry1.grid(row=0, column=1)

def update(*args):
    try:
        for i in range(1, n_para.get()+1):
            entryX = Entry(root)
            entryX.grid(row=i+1, column=0)
            entryY = Entry(root)
            entryY.grid(row=i+1, column=1)
            entryZ = Entry(root)
            entryZ.grid(row=i+1, column=2)
    except ValueError:
        return

n_para.trace_add('write', update)

root.mainloop()

When I enter a number, it works and an error raises: _tkinter.TclError: expected floating-point number but got "" which I don’t know what is that for.

Also, the code only works when I put numbers in ascending format. forexample, if I first enter 5, then change it to 3 it doesn’t work.

Advertisement

Answer

You should use StringVar to associate with the Entry, as the entry contains text.

There is a method in StringVar to trace any changes: StringVar().trace(). Se example code below:

from tkinter import *

root = Tk()
root.geometry("400x400")

n_para = StringVar()

label1 = Label(root, text="Numeric parameters")
label1.grid(row=0, column=0)

entry1 = Entry(root, textvariable=n_para)
entry1.grid(row=0, column=1)

def update(*args):
    print('update', n_para.get())

n_para.trace('w', update)   # Trace changes in n_para and run update if detected

root.mainloop()

The error you get is because the Entry contains text. You will have to convert it to int before you use it.

New example

You could do this in many ways, but here is one example:

from tkinter import *

root = Tk()
root.geometry("400x400")

n_para = StringVar()

label1 = Label(root, text="Numeric parameters")
label1.grid(row=0, column=0)

entry1 = Entry(root, textvariable=n_para)
entry1.grid(row=0, column=1)

row_list = []       # List of all currently displayed entry rows
                    # and each row is a list of entrys within this list

def update(*args):
    try:
        para = int(n_para.get())
    except ValueError:
        return      # Return without changes if ValueError occurs
    
    rows = len(row_list)
    diff = para - rows  # Compare old number of rows with entry value
    if diff == 0:
        return      # Return without changes
    
    elif diff > 0:      # Add rows of entrys and remember them
        for row in range(rows+1, rows+diff+1):
            entry_list = []   # Local list for entrys on this row
            for col in range(3):
                e = Entry(root)
                e.grid(row=row, column=col)
                entry_list.append(e)    # Add entry to list
            row_list.append(entry_list) # Add entry list to row
    
    elif diff < 0:      # Remove rows of entrys and froget them
        for row in range(rows-1, rows-1+diff, -1):
            for widget in row_list[row]:
                widget.grid_forget()
                widget.destroy()
            del row_list[-1]

n_para.trace('w', update)   # Trace changes in n_para

root.mainloop()

Is that what you had in mind?

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement