Constantly Update Label Widgets From Entry Widgets TKinter - python

I am trying to make a form using TKinter that takes information from a/multiple entry widget(s) and uses them as the value for text widgets. For example, this could work:
import Tkinter
from Tkinter import *
top = Tk()
e1 = Entry(top)
e2 = Entry(top)
t = Label(top, text = e1.get() + e2.get())
e1.pack()
e2.pack()
t.pack()
top.mainloop()
The issue is that this does not automatically update itself. I know it could be done using a button, but I would like to have the information calculated/updated in the Label widget as the user types into the Entry widgets. What would be the best was to do this? The following implementation of a while loop does not work as the program enters the top.mainloop() and does not exit:
import Tkinter
from Tkinter import *
top = Tk()
e1 = Entry(top)
e2 = Entry(top)
t = Label(top, text = e1.get() + e2.get())
e1.pack()
e2.pack()
while True:
t = Label(top, text = e1.get() + e2.get())
t.pack()
top.mainloop()
Thank you in advance.
Six

while True will not work because mainloop() is some kind of while True loop and it works all the time till you stop program.
You have to use after(time_in_millisecond, function_name) which add function_name to special queue and mainloop() will run it (only once) after time_in_millisecond. Executed function can use after() to run itself again after time_in_millisecond.
Second solution: You can use StringVar with Entry and you can assign function to StringVar (using trace()) and this function will be executed every time when StringVar will be changed.
Third solution: you can bind event (<Key>) to Entry which will call some function when you press key in Entry.
Last solution: You can use validatecommand= with validate= in Entry to call some function when text in entry will be changed.
See Tkinterbook:
The Tkinter Entry Widget,
Events and Bindings,
The Variable Classes (BooleanVar, DoubleVar, IntVar, StringVar)
EDIT:
Example with validatecommand= with validate= .
Not all widgets have validatecommand=
from Tkinter import *
#------------------------------------
def my_validater():
new_text = e1.get() + e2.get()
# different method to set label text (without StringVar)
#t['text'] = new_text
t.config(text=new_text)
# validater have to return True or False
return True
#------------------------------------
top = Tk()
#---
t = Label(top)
t.pack()
#---
e1 = Entry(top, validate='key', validatecommand=my_validater) # validate every key
e1.pack()
#---
e2 = Entry(top, validate='key', validatecommand=my_validater) # validate every key
e2.pack()
#---
top.mainloop()
#------------------------------------
Example with StringVar and trace
Probably the best solution for most widgets.
from Tkinter import *
#------------------------------------
def my_tracer(a, b, c): # trace send 3 arguments to my_tracer
#print a, b, c
# using StringVar to get and set text
new_text = e1_var.get() + e2_var.get()
t_var.set(new_text)
#------------------------------------
top = Tk()
#---
t_var = StringVar() # or StringVar(top)
t = Label(top, textvariable=t_var)
t.pack()
#---
e1_var = StringVar() # or StringVar(top)
e1_var.trace('w', my_tracer) # run my_tracer if value was changed (w = write)
e1 = Entry(top, textvariable=e1_var)
e1.pack()
#---
e2_var = StringVar() # or StringVar(top)
e2_var.trace('w', my_tracer) # run my_tracer if value was changed (w = write)
e2 = Entry(top, textvariable=e2_var)
e2.pack()
#---
top.mainloop()
#------------------------------------
Example with bind(<Key>, ...)
Binded function is called before char is placed in Entry so you get text without last char in Entry. This method is not good for this situation but I keep it.
Eventually you can get event.char and add missing char to text.
from Tkinter import *
#------------------------------------
def my_bind(event): # bind send 1 argument to my_bind
# different type of event can have different atributes
#print event, event.widget, event.char, event.keysym, event.keycode
new_text = e1.get() + e2.get()
t.config(text=new_text)
#------------------------------------
top = Tk()
#---
t = Label(top)
t.pack()
#---
e1 = Entry(top)
e1.pack()
e1.bind('<Key>', my_bind)
#---
e2 = Entry(top)
e2.pack()
e2.bind('<Key>', my_bind)
#---
top.mainloop()
#------------------------------------
Example with after().
Used for different repeated jobs.
from Tkinter import *
#------------------------------------
def my_after():
new_text = e1.get() + e2.get()
t.config(text=new_text)
# call again after 100 ms
top.after(100, my_after)
#------------------------------------
top = Tk()
#---
t = Label(top)
t.pack()
#---
e1 = Entry(top)
e1.pack()
#---
e2 = Entry(top)
e2.pack()
#---
# call first time
my_after()
# call first time after 100 ms
#top.after(100, my_after)
#---
top.mainloop()
#------------------------------------

Related

How to change values from a matrix GUI tkinter?

I want to change a number from a matrix and then display it in the same tk window, but I find it hard to work with variables from an input. The r[][] should be the matrix formed with the user's input. And after all I have to display the matrix with the modification: r[0][1] += 5, in the same tk window.
from tkinter import *
import numpy as np
root = Tk()
def process():
values = [e1.get(),e2.get(),e3.get(),e4.get()]
a = np.zeros((2,2),dtype=np.int64)
for i in range(2):
for j in range(2):
a[i][j] = values[i*2+j]
print(a)
e1 = Entry(root)
e2 = Entry(root)
e3 = Entry(root)
e4 = Entry(root)
e1.grid(row=0,column=0,padx=10,pady=10)
e2.grid(row=0,column=1)
e3.grid(row=1,column=0,padx=10,pady=10)
e4.grid(row=1,column=1)
b = Button(root,text='Process',command=process)
b.grid(row=2,column=0,columnspan=4,sticky=E+W)
root.mainloop()
r=[[e1.get(),e2.get()],[e3.get(),e4.get()]]
r[0][1] += 5
Tkinter GUI programs are event-driven which requires using a different programming paradigm than the one you're probably familiar with which is called imperative programming. In other words, just about everything that happens is done in response to something the user has done, like typing on the keyboard, clicking on a graphical button, moving the mouse, etc.
I think the code below will give you a good idea of how to do what you want in a framework like that. It creates a StringVar for each Entry widget, which has the advantage what's displayed in each Entry will automatically be updated whenever the corresponding StringVar is changed (make that more-or-less automatic).
To determine which StringVar is associated with a given Entry, a separate dictionary is created which maps the internal tkinter variable name to corresponding Python variable. The internal tkinter variable name is obtained by using the universal cget() widget method.
import tkinter as tk
from tkinter.constants import *
ROWS, COLS = 2, 2
def process(entry_widgets, row, col):
var_name = entry_widgets[row][col].cget('textvariable')
var = root.variables[var_name]
try:
value = float(var.get())
except ValueError: # Something invalid (or nothing) was entered.
value = 0
var.set(value+5) # Update value.
root = tk.Tk()
# Create a grid of Entry widgets.
entries = []
root.variables = {} # To track StringVars.
for x in range(COLS):
row = []
for y in range(ROWS):
var = tk.StringVar(master=root) # Create variable.
root.variables[str(var)] = var # Track them by name.
entry = tk.Entry(root, textvariable=var)
entry.grid(row=x, column=y)
row.append(entry)
entries.append(row)
btn = tk.Button(root, text='Process', command=lambda: process(entries, 0, 1))
btn.grid(row=2, column=0, columnspan=COLS, sticky=E+W)
root.mainloop()
Would this be what you're looking for? I deleted a bunch of code that seems to do nothing in context -- you just want to replace the text in the corner box right?
from tkinter import *
def process():
replace(e4)
def replace(entry_loc):
temp = int(entry_loc.get())
temp += 5
entry_loc.delete(0,500)
entry_loc.insert(0, temp)
root = Tk()
var_e1 = StringVar
var_e2 = StringVar
var_e3 = StringVar
var_e4 = StringVar
e1 = Entry(root, textvariable=var_e1)
e2 = Entry(root, textvariable=var_e2)
e3 = Entry(root, textvariable=var_e3)
e4 = Entry(root, textvariable=var_e4)
e1.grid(row=0, column=0, padx=10, pady=10)
e2.grid(row=0, column=1)
e3.grid(row=1, column=0, padx=10, pady=10)
e4.grid(row=1, column=1)
b = Button(root, text='Process', command=process)
b.grid(row=2, column=0, columnspan=4, sticky=E + W)
root.mainloop()

python-entry widget Place change is not going to happen and Label creating problem

the code is presented below but not relocated entry widget place, label is also not created. before entered this code [ e1.grid(row=1,column=1) ] the program working perfectly, after entering the code not working, how to handle this problem..
the program is
try :
import tkinter as tk # Python 3
except :
import Tkinter as tk # Python 2
def update_sum() :
# Sets the sum of values of e1 and e2 as val of e3
try :
sum_tk.set((float(e1_tk.get().replace(' ', '')) + float(e2_tk.get().replace(' ', ''))))
except :
pass
root.after(10, update_sum) # reschedule the event
return
root = tk.Tk()
root.geometry('850x450')
e1_tk = tk.StringVar(root) # Initializes a text variable of tk to use to get e1's val.
e2_tk = tk.StringVar(root) # Initializes a text variable of tk to use to get e2's val.
sum_tk = tk.StringVar(root) # Initializes a text variable of tk to use to set e3's val.
# Entries
e1 = tk.Entry(root, textvariable = e1_tk)
e1.grid(row=1,column=1)
e2 = tk.Entry(root, textvariable = e2_tk)
e2.grid(row=1,column=2)
e3 = tk.Entry(root, textvariable = sum_tk)
e3.grid(row=1,column=3)
e1=Label(root,text="SL")
e1.grid(row=1,column=0)
e1.pack()
e2.pack()
e3.pack()
# Will update the sum every second 10 ms = 0.01 second it takes ms as arg.
root.after(10, update_sum)
root.mainloop()
Thanks in Advance..
You are using the same variable for 2 widgets and using the grid function on it
Grid and pack are 2 of the build-in layout managers including the place
We can only use one of these on a single element
In your program you are packing e1,e2,e3 and trying to give them a grid layout.
Also you are using e1.grid() twice with different column values .
try :
import tkinter as tk # Python 3
except :
import Tkinter as tk # Python 2
def update_sum() :
# Sets the sum of values of e1 and e2 as val of e3
try :
sum_tk.set((float(e1_tk.get().replace(' ', '')) + float(e2_tk.get().replace(' ', ''))))
except :
pass
root.after(10, update_sum) # reschedule the event
return
root = tk.Tk()
root.geometry('850x450')
e1_tk = tk.StringVar(root) # Initializes a text variable of tk to use to get e1's val.
e2_tk = tk.StringVar(root) # Initializes a text variable of tk to use to get e2's val.
sum_tk = tk.StringVar(root) # Initializes a text variable of tk to use to set e3's val.
# Entries
e1 = tk.Entry(root, textvariable = e1_tk)
e1.grid(row=1,column=1)
e2 = tk.Entry(root, textvariable = e2_tk)
e2.grid(row=1,column=2)
e3 = tk.Entry(root, textvariable = sum_tk)
e3.grid(row=1,column=3)
e4=tk.Label(root,text="SL")
e4.grid(row=1,column=0)
# Will update the sum every second 10 ms = 0.01 second it takes ms as arg.
root.after(10, update_sum)
root.mainloop()

How do I get the Entry's value in tkinter?

I'm trying to use Tkinter's Entry widget. I can't get it to do something very basic: return the entered value. Does anyone have any idea why such a simple script would not return anything? I've tried tons of combinations and looked at different ideas.
This script runs but does not print the entry:
from Tkinter import *
root = Tk()
E1 = Entry(root)
E1.pack()
entry = E1.get()
root.mainloop()
print "Entered text:", entry
Seems so simple.
Edit
In case anyone else comes across this problem and doesn't understand, here is what ended up working for me. I added a button to the entry window. The button's command closes the window and does the get() function:
from Tkinter import *
def close_window():
global entry
entry = E.get()
root.destroy()
root = Tk()
E = tk.Entry(root)
E.pack(anchor = CENTER)
B = Button(root, text = "OK", command = close_window)
B.pack(anchor = S)
root.mainloop()
And that returned the desired value.
Your first problem is that the call to get in entry = E1.get() happens even before your program starts, so clearly entry will point to some empty string.
Your eventual second problem is that the text would anyhow be printed only after the mainloop finishes, i.e. you close the tkinter application.
If you want to print the contents of your Entry widget while your program is running, you need to schedule a callback. For example, you can listen to the pressing of the <Return> key as follows
import Tkinter as tk
def on_change(e):
print e.widget.get()
root = tk.Tk()
e = tk.Entry(root)
e.pack()
# Calling on_change when you press the return key
e.bind("<Return>", on_change)
root.mainloop()
from tkinter import *
import tkinter as tk
root =tk.Tk()
mystring =tk.StringVar(root)
def getvalue():
print(mystring.get())
e1 = Entry(root,textvariable = mystring,width=100,fg="blue",bd=3,selectbackground='violet').pack()
button1 = tk.Button(root,
text='Submit',
fg='White',
bg= 'dark green',height = 1, width = 10,command=getvalue).pack()
root.mainloop()

In Tkinter, How I disable Entry?

How I disable Entry in Tkinter.
def com():
....
entryy=Entry()
entryy.pack()
button=Button(text="Enter!", command=com, font=(24))
button.pack(expand="yes", anchor="center")
As I said How I disable Entry in com function?
Set state to 'disabled'.
For example:
from tkinter import *
root = Tk()
entry = Entry(root, state='disabled')
entry.pack()
root.mainloop()
or
from tkinter import *
root = Tk()
entry = Entry(root)
entry.config(state='disabled') # OR entry['state'] = 'disabled'
entry.pack()
root.mainloop()
See Tkinter.Entry.config
So the com function should read as:
def com():
entry.config(state='disabled')
if we want to change again and again data in entry box we will have to first convert into Normal state after changing data we will convert in to disable state
import tkinter as tk
count = 0
def func(en):
en.configure(state=tk.NORMAL)
global count
count += 1
count=str(count)
en.delete(0, tk.END)
text = str(count)
en.insert(0, text)
en.configure(state=tk.DISABLED)
count=int(count)
root = tk.Tk()
e = tk.Entry(root)
e.pack()
b = tk.Button(root, text='Click', command=lambda: func(e))
b.pack()
root.mainloop()

Accepting inputs from Tkinter

I want to write a GUI in Tkinter that accepts a text inputs from the user and stores it in a variable Text; I also want to be able to use this variable later on... Here is something i tried that failed:
from Tkinter import *
def recieve():
text = E1.get()
return text
top = Tk()
L1 = Label(top, text="User Name")
L1.pack(side=LEFT)
E1 = Entry(top, bd=5)
E1.pack(side=RIGHT)
b = Button(top, text="get", width=10, command=recieve)
b.pack()
print text
top.mainloop()
So how do I do this?
The problem lies here:
print text
top.mainloop()
Before top.mainloop() is called, text has not been defined. Only after the call to top.mainloop is the user presented with the GUI interface, and the mainloop probably loops many many times before the user gets around to typing in the Entry box and pressing the Button. Only after the button is pressed is recieve (sic) called, and although it returns a value, that value is not stored anywhere after recieve ends. If you want to print text, you have to do it in the recieve function:
from Tkinter import *
def receive():
text = E1.get()
print(text)
top = Tk()
L1 = Label(top, text="User Name")
L1.pack( side = LEFT)
E1 = Entry(top, bd =5)
E1.pack(side = RIGHT)
b = Button(top, text="get", width=10, command=receive)
b.pack()
top.mainloop()

Categories