Mar-04-2024, 07:28 PM
(This post was last modified: Mar-04-2024, 07:30 PM by deanhystad.)
Next time post a short example that demonstrates the problem.
There is a big problem with your approach: A vast majority of strings raise an error when converted to float. Even typing in valid numeric strings can cause an error because the string is not always valid when typed in. For example, typing "-4" will raise an error when you press the "-" key.
Knowing that most strings will raise a ValueError, your trace function must allow for the error to occur without crashing the application.
This example only updates the value when you press the enter key or the Entry loses focus.
There is a big problem with your approach: A vast majority of strings raise an error when converted to float. Even typing in valid numeric strings can cause an error because the string is not always valid when typed in. For example, typing "-4" will raise an error when you press the "-" key.
Knowing that most strings will raise a ValueError, your trace function must allow for the error to occur without crashing the application.
import tkinter as tk class Window(tk.Tk): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.var = tk.StringVar(self, "") self.var.trace_add("write", self.trace_func) tk.Entry(self, width=10, textvariable=self.var).pack(padx=10, pady=10) self.label = tk.Label(self, text="") self.label.pack(padx=10, pady=10) def trace_func(self, *_): try: self.label["text"] = str(float(self.var.get())**2) except ValueError: pass Window().mainloop()This works but notice that the displayed value changes each time you press a key. Do you really want that? When entering a number do you want to call your function each time a key is pressed, or do you want to wait for the entire number to be entered?
This example only updates the value when you press the enter key or the Entry loses focus.
import tkinter as tk class FloatEntry(tk.Entry): """Custom Entry widget for float values. Value updates when Return is pressed or widget loses focus. """ def __init__(self, *args, command=None, **kwargs): self.var = tk.StringVar() super().__init__(*args, textvariable=self.var, **kwargs) self.command = command self.bind("<Return>", self._update_value) self.bind("<FocusOut>", self._update_value) self._value = 0 self.var.set(str(self._value)) @property def value(self): """Get current value.""" return self._value @value.setter def value(self, value): """Set current value.""" self.var.set(str(value)) def _update_value(self, *_): """Validate input and call command function.""" try: self._value = float(self.var.get()) if self.command: self.command(self._value) except ValueError: # Revert to previous good value. self.var.set(str(self._value)) class Window(tk.Tk): """Display product of two numbers.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.a = FloatEntry(self, command=self.update_display) self.b = FloatEntry(self, command=self.update_display) self.product = tk.Label(self, text="") self.a.pack(padx=10, pady=10) self.b.pack(padx=10, pady=10) self.product.pack(padx=10, pady=10) def update_display(self, *_): self.product["text"] = str(self.a.value * self.b.value) Window().mainloop()