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.
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?
Related
I want to update getting results from an entry box in a way that when an integer enters, the equivalent rows of entry boxes appear below that. I have written the below code to make it work using a button. However, I want to make it happen automatically without a button as I entered the number, the rows update. I checked one way of doing that is using the after(). I placed after after() in the function and out of the function but it is not working.
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)
root.after(100, update)
root.after(1, update)
button1 = Button(root, text="update", command=update)
button1.grid(row=1, column=0)
root.mainloop()
You should try using the <KeyRelease> event bind.
import tkinter as tk
def on_focus_out(event):
label.configure(text=inputtxt.get())
root = tk.Tk()
label = tk.Label(root)
label.pack()
inputtxt = tk.Entry()
inputtxt.pack()
root.bind("<KeyRelease>", on_focus_out)
root.mainloop()
This types the text entered in real-time.
Edited Code with OP's requirement:
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 upd(event):
x = entry1.get()
if not x.isnumeric():
x = 0
for i in range(1, int(x)+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)
# root.after(100, update)
root.bind("<KeyRelease>", upd)
# button1 = Button(root, text="update", command=update)
# button1.grid(row=1, column=0)
root.mainloop()
a newbie here,
i have read every post that can be related to my problem but did not solve it.
i am tryin to get the input from user to a list and then show it to the user, but nothing happens.
here is the code:
from tkinter import *
root = Tk()
root.title("MyApp")
root.geometry("700x500")
my_entries = []
def something():
entry_list = ''
for entries in my_entries:
entry_list = entry_list + str(entries.get()) + '\n'
my_label.config(text=entry_list)
for x in range(3):
my_entry = Entry(root)
my_entry.grid(row=0, column=x, pady=20, padx=5)
my_button = Button(root, text="set", command=something)
my_button.grid(row=1, column=0, pady=20)
my_label = Label(root, text='Total Income')
my_label.grid(row=4, column=0, pady=20)
root.mainloop()
You didn't append the entries to my_entries. Here is what the for loop should look like:
for x in range(3):
my_entry = Entry(root)
my_entry.grid(row=0, column=x, pady=20, padx=5)
my_entries.append(my_entry)
The point of this is to press a button and have new rows appear but currently, titles appear above each new row that is added. Instead, I would like to have one row at the top of the grid with column titles. Is there a way to modify this code I already have? Later, I will be incorporating this into a larger tkinter GUI.
from tkinter import *
#------------------------------------
def addbox():
frame =Frame(root)
frame.pack()
#Item
Label(frame, text="Item").grid(row=0, column=0)
ent1 = Entry(frame, width=10)
ent1.grid(row=2, column=0)
#Day
Label(frame, text="Day").grid(row=0, column=1)
ent2 = Entry(frame, width=10)
ent2.grid(row=2, column=1)
#Code
ent3 = Entry(frame, width=10)
ent3.grid(row=2, column=2)
#Factor
ent4 = Entry(frame, width=10)
ent4.grid(row=2, column=3)
all_entries.append( (ent1, ent2, ent3, ent4) )
#Buttons.
showButton = Button(frame, text='Print', command=refresh)
addboxButton = Button(frame, text='Add Item', fg="Red", command=addbox)
#------------------------------------
def refresh():
for number, (ent1, ent2, ent3, ent4) in enumerate(all_entries):
print (number, ent1.get(), ent2.get(), ent3.get(),ent4.get())
#------------------------------------
all_entries = []
root = Tk()
addboxButton = Button(root, text='Add Instrument', fg="Red", command=addbox)
addboxButton.pack()
root.mainloop()
You can check the row count before you add the label:
if len(all_entries) < 1:
Label(frame, text="Item").grid(row=0, column=0)
I am trying to use a loop to create multiple drop down menus based on an entry in a entry text box after submit is pressed. I have never worked with tkinter before so I am not sure if I am doing this correctly. Any help would be appreciated. the code I have below is what I have but it causes the program to enter into some kind of infinite loop
from Tkinter import *
def callback():
numQues = E1.get()
i = 0
while i < numQues:
variable = StringVar(top)
variable.set("Short Answer") # default value
w = OptionMenu(top, variable, "Short Answer", "Multiple Choice", "Fill in the Blank",
"True of False", "Mathcing", "Ordering")
w.grid(row = i+1, column=0)
i = i+1
top = Tk()
top.geometry("600x600")
L1 = Label(top, text="How many questions will the quiz be?")
L1.grid(row=0, column=0)
E1 = Entry(top, bd = 5)
E1.grid(row=0, column=1)
MyButton1 = Button(top, text="Submit", width=10, command=callback)
MyButton1.grid(row=1, column=1)
top.mainloop()
I am trying to write a program where you enter a number in to an entry box click a button and it prints the number you entered and it prints the number you entered multiplied by 0.008.
Then stores the numbers so the next time you enter a number it adds it to the previous number and prints it and so on so forth. I have written the first bit of code and it works well. But no matter how much research I do I cannot find out how to do the second bit. This is my code so far.
from tkinter import *
def calculatemoney():
done = float(Lines1.get())
salary3 = done * 0.08
salary4 = done * 1
labelresult = Label(root, text='%.0f' % salary4).grid(row=3, column=2)
labelresult = Label(root, text=' £ %.2f' % salary3).grid(row=4, column=2)
root = Tk()
root.title('Dict8 Calc')
root.geometry('250x200+800+100')
Lines1 = StringVar()
var1 = Label(root, text='Enter Lines').grid(row=0, column=1)
var2 = Label(root, text='Lines Today').grid(row=3, column=1)
var3 = Label(root, text='Money Today').grid(row=4, column=1)
var4 = Label(root, text='Lines Total').grid(row=6, column=1)
var5 = Label(root, text='Money Total').grid(row=7, column=1)
myLines = Entry(root, textvariable=Lines1).grid(row=0, column=2)
button1 = Button(root, text=' Calculate ', command=calculatemoney).grid(row=8, column=2)
root.mainloop()
What's stopping you from using a regular variable ?
from tkinter import *
def calculatemoney():
global oldValue # Making it global so you can set it's value
done = float(Lines1.get())
salary3 = done * 0.08
salary4 = done
salary5 = (done + oldValue) * 0.8 # Adding the old value to the new one
salary6 = done + oldValue
Label(root, text='%.0f' % salary4).grid(row=3, column=2) # I don't recommend this method of putting a label over another every time the user activates this function
Label(root, text=' f %.2f' % salary3).grid(row=4, column=2)
Label(root, text='%.0f' % salary6).grid(row=6, column=2)
Label(root, text=' f %.2f' % salary5).grid(row=7, column=2)
oldValue += done # Adding the current value to the old value
root = Tk()
oldValue = 0.0 # Define variable that will represent an old value
root.title('Dict8 Calc')
root.geometry('250x200+800+100')
Lines1 = StringVar()
var1 = Label(root, text='Enter Lines').grid(row=0, column=1) # .grid() method returns 'None' so you dont have any use for 'var1'.
var2 = Label(root, text='Lines Today').grid(row=3, column=1)
var3 = Label(root, text='Money Today').grid(row=4, column=1)
var4 = Label(root, text='Lines Total').grid(row=6, column=1) # Shouldn't it be 'row=5' ?
var5 = Label(root, text='Money Total').grid(row=7, column=1)
myLines = Entry(root, textvariable=Lines1).grid(row=0, column=2)
button1 = Button(root, text=' Calculate ', command=calculatemoney).grid(row=8, column=2)
root.mainloop()