I'm trying to make a simple temperature conversion calculator in python. What I want to do is to be able to type in a number, and have the other side automatically update, without having to push a button. Right now I can only get it to work in one direction. I can either code it so that it can go from F to C, or C to F. But not either way.
Obviously after
is not the way to go. I need some kind of onUpdate
or something. TIA!
import Tkinter as tk
root = tk.Tk()
temp_f_number = tk.DoubleVar()
temp_c_number = tk.DoubleVar()
tk.Label(root, text="F").grid(row=0, column=0)
tk.Label(root, text="C").grid(row=0, column=1)
temp_f = tk.Entry(root, textvariable=temp_f_number)
temp_c = tk.Entry(root, textvariable=temp_c_number)
temp_f.grid(row=1, column=0)
temp_c.grid(row=1, column=1)
def update():
temp_f_float = float(temp_f.get())
temp_c_float = float(temp_c.get())
new_temp_c = round((temp_f_float - 32) * (5 / float(9)), 2)
new_temp_f = round((temp_c_float * (9 / float(5)) + 32), 2)
temp_c.delete(0, tk.END)
temp_c.insert(0, new_temp_c)
temp_f.delete(0, tk.END)
temp_f.insert(0, new_temp_f)
root.after(2000, update)
root.after(1, update)
root.mainloop()
We will create an event callback function by specifying the variable that stores the user input. By using the trace("mode", lambda variable, variable: callback()) method with the variable, we can trace the input on the Label widget in the window.
Update method processes all the pending idle tasks, unvisited events, calling functions, and callbacks. The method is applicable for updating and processing all the events or tasks such as redrawing widgets, geometry management, configuring the widget property, etc.
As previously stated, the best way to get the latest version of Tkinter is to install Python 3.7 or later. But Tkinter can also be downloaded and installed as part of any standard Python 3 installation.
_ClassType IntVarConstruct an integer variable. set(self, value) Set the variable to value, converting booleans to integers. get(self) Return the value of the variable as an integer.
What you are looking for is variable trace() method. E.g.:
def callback(*args):
print "variable changed!"
var = DoubleVar()
var.trace("w", callback)
Attach trace callbacks for each of your DoubleVar, for temp_f_number one to update the temp_c_number value and vice versa. You'll likely also need to disable one callback function while inside another one, to avoid recursive update cycle.
Another note - do not edit the Entry fields. Instead, use variables' set() method. Entry fields will be updated automatically.
So, complete code could look like this:
import Tkinter as tk
root = tk.Tk()
temp_f_number = tk.DoubleVar()
temp_c_number = tk.DoubleVar()
tk.Label(root, text="F").grid(row=0, column=0)
tk.Label(root, text="C").grid(row=0, column=1)
temp_f = tk.Entry(root, textvariable=temp_f_number)
temp_c = tk.Entry(root, textvariable=temp_c_number)
temp_f.grid(row=1, column=0)
temp_c.grid(row=1, column=1)
update_in_progress = False
def update_c(*args):
global update_in_progress
if update_in_progress: return
try:
temp_f_float = temp_f_number.get()
except ValueError:
return
new_temp_c = round((temp_f_float - 32) * 5 / 9, 2)
update_in_progress = True
temp_c_number.set(new_temp_c)
update_in_progress = False
def update_f(*args):
global update_in_progress
if update_in_progress: return
try:
temp_c_float = temp_c_number.get()
except ValueError:
return
new_temp_f = round(temp_c_float * 9 / 5 + 32, 2)
update_in_progress = True
temp_f_number.set(new_temp_f)
update_in_progress = False
temp_f_number.trace("w", update_c)
temp_c_number.trace("w", update_f)
root.mainloop()
.trace
is soon to be deprecated, use .trace_add
instead:
var = tk.StringVar()
var.trace_add('write', callback)
Same functionality, but you must pass write
or read
instead of w
or r
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With