简体   繁体   中英

Constantly Update Label Widgets From Entry Widgets TKinter

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()

#------------------------------------

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM