Interactive Entry widgets

59 Views Asked by At

Is it possible to have 2 entry widgets that are interactive, I'm thinking about conversions here, so for example Miles to Kilo-meters & vice-versa; as I enter data into one widget, it is automatically updated in the other widget, regardless of which one I start with.

Below is my starting point, but I need the entry widgets to be sensitive to "Key" and call a respective function?

from tkinter import *
from tkinter import messagebox

root = Tk()
root.title("Conversions")
root.geometry("500x200")

ent_pound = Entry(root, width=20)
ent_pound.grid(row=0,column=0)

ent_kilo = Entry(root, width=20)
ent_kilo.grid(row=1,column=0)

value_pound=eval(ent_pound.get())
ent_kilo.delete(0,END)
ent_kilo.insert(0,repr(value*0.453592))

value_kilo=eval(ent_kilo.get())
ent_pound.delete(0,END)
ent_pound.insert(0,repr(value/0.453592))
`
root.mainloop()
2

There are 2 best solutions below

0
Henry On

The best way to do this is using Tkinter variables. You can create a DoubleVar for each entry, then add a trace to call a function on write. The variables are then bound to the entries with the textvariable attribute.

You can then use the get and set methods of the variables to do the conversion. The conversion is wrapped in a try/except to ignore the error from get if the entry is empty.

from tkinter import *
from tkinter import messagebox

root = Tk()
root.title("Conversions")
root.geometry("500x200")

pound_var = DoubleVar()
kilo_var = DoubleVar()

def set_kilo(*args):
    try:
        value = pound_var.get()
        kilo_var.set(value*0.453592)
    except: pass

def set_pound(*args):
    try:
        value = kilo_var.get()
        pound_var.set(value/0.453592)
    except: pass

pound_var.trace_add("write", set_kilo)
ent_pound = Entry(root, width=20, textvariable = pound_var)
ent_pound.grid(row=0,column=0)

kilo_var.trace_add("write", set_pound)
ent_kilo = Entry(root, width=20, textvariable = kilo_var)
ent_kilo.grid(row=1,column=0)

root.mainloop()

If you don't like how DoubleVar prefills the entry, you could use StringVar instead and convert the input

pound_var = StringVar()
kilo_var = StringVar()

def set_kilo(*args):
    try:
        value = float(pound_var.get())
        kilo_var.set(value*0.453592)
    except: pass

def set_pound(*args):
    try:
        value = float(kilo_var.get())
        pound_var.set(value/0.453592)
    except: pass
0
shahriar On

Do this with your entry widget:

def on_entry_key_press(event):
    # Your code here


entry.bind("<Key>", on_entry_key_press)

Here, on_entry_key_press is a method that will call when any key is pressed while entry is focused. Remember, you have to bind your entry before place/pack/grid. And if you want to get which key is pressed, then you can get that by event.char.