Reputation: 793
So I'm trying to create something like the goole unit conversion tool So far I have this:
import tkinter
rate = 3.281
def command_P():
print("button pressed")
def callback1(arg):
try:
float(amount1.get())
amount2.delete(0,"end")
amount2.insert(0,float(amount1.get())*rate)
except Exception as e:
print(e)
def callback2(arg):
try:
float(amount2.get())
amount1.delete(0,"end")
amount1.insert(0,float(amount2.get())/rate)
except Exception as e:
print(e)
trade_w = tkinter.Tk()
trade_w.title("Unit Converter")
label_mont1 = tkinter.Label(trade_w,
text = "Metre:")
label_mont1.grid(column=0, row=1)
sv = tkinter.StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: callback1(sv))
amount1 = tkinter.Entry(trade_w,textvariable=sv)
amount1.grid(column=1, row=1)
label_mont2 = tkinter.Label(trade_w,
text = "Foot:")
label_mont2.grid(column=2, row=1)
vs = tkinter.StringVar()
vs.trace("w", lambda name, index, mode, vs=vs: callback2(vs))
amount2 = tkinter.Entry(trade_w, textvariable=vs)
amount2.grid(column=3, row=1)
trade_w.mainloop()
Everything seem to work fine but when I write something on either box it moves the text cursor to the end of the Entry box, thats becouse when I do the .get() for amount1 or amount2 it does the callback function and recalculate the value.
Any idea of how to bypass or solve this?
Thanks!
Upvotes: 0
Views: 52
Reputation: 46678
You can use <KeyRelease>
event callback instead of tracing change of tkinter variable:
import tkinter
rate = 3.281
def on_entry_change(event):
try:
if event.widget is amount1:
value = float(sv.get())
vs.set(value * rate)
else:
value = float(vs.get())
sv.set(value / rate)
except Exception as e:
print(e)
trade_w = tkinter.Tk()
trade_w.title("Unit Converter")
label_mont1 = tkinter.Label(trade_w, text="Metre:")
label_mont1.grid(column=0, row=1)
sv = tkinter.StringVar()
amount1 = tkinter.Entry(trade_w, textvariable=sv)
amount1.grid(column=1, row=1)
amount1.bind('<KeyRelease>', on_entry_change)
label_mont2 = tkinter.Label(trade_w, text="Foot:")
label_mont2.grid(column=2, row=1)
vs = tkinter.StringVar()
amount2 = tkinter.Entry(trade_w, textvariable=vs)
amount2.grid(column=3, row=1)
amount2.bind('<KeyRelease>', on_entry_change)
trade_w.mainloop()
Upvotes: 0
Reputation: 385970
Since you know (or can determine) which widget has focus, just have the callback do nothing unless the focus is in a particular window.
def callback1(arg):
if trade_w.focus_get() == amount1:
try:
float(amount1.get())
amount2.delete(0,"end")
amount2.insert(0,float(amount1.get())*rate)
except Exception as e:
print(e)
def callback2(arg):
if trade_w.focus_get() == amount2:
try:
float(amount2.get())
amount1.delete(0,"end")
amount1.insert(0,float(amount2.get())/rate)
except Exception as e:
print(e)
There are more efficient ways to do that, but this illustrates the point that you can determine which widget has the focus so that you only update the other widget.
Upvotes: 1