we are coding an app that is a converter. So there are 8 text fields in the app (from .kv file). We use on_text parameter to update the other text fields accordingly, but when we update a certain amount of fields, it runs in a loop and crashes the app with a RecursionError. The problem is that the on_text parameter executes the functions inside of it not only when the text inside the field is changed by the user but also when the text parameter is changed from the code. Is there any way to only run it when it's changed by the user, no matter if it's a keyboard or touchscreen, and only inside the KV file without any additional python code?
Here is the part of the code that gives the problem:
BoxLayout:
orientation: "vertical"
pos: 0, root.height - 30
spacing: "30dp"
size_hint: .9, .7
pos_hint: {"center_x": .5, "center_y": .5}
MDTextField:
id:millimeterfield
hint_text: "Millimeters"
on_text:
centimeterfield.text = str(float(millimeterfield.text) / 10).rstrip('0').rstrip('.') if millimeterfield.text != "" else "0"
meterfield.text = str(float(millimeterfield.text) / 1000).rstrip('0').rstrip('.') if millimeterfield.text != "" else "0"
kilometerfield.text = str(float(millimeterfield.text) / 1000000).rstrip('0').rstrip('.') if millimeterfield.text != "" else "0"
inchfield.text = str(float(millimeterfield.text) / 25.4).rstrip('0').rstrip('.') if millimeterfield.text != "" else "0"
feetfield.text = str(float(millimeterfield.text) / 305).rstrip('0').rstrip('.') if millimeterfield.text != "" else "0"
yardfield.text = str(float(millimeterfield.text) / 914).rstrip('0').rstrip('.') if millimeterfield.text != "" else "0"
milefield.text = "0"
MDTextField:
hint_text: "Centimeters"
id: centimeterfield
on_text:
millimeterfield.text = str(float(centimeterfield.text) * 10).rstrip('0').rstrip('.') if centimeterfield.text != "" else "0"
meterfield.text = str(float(centimeterfield.text) / 100).rstrip('0').rstrip('.') if centimeterfield.text != "" else "0"
kilometerfield.text = str(float(centimeterfield.text) / 100000).rstrip('0').rstrip('.') if centimeterfield.text != "" else "0"
inchfield.text = str(float(centimeterfield.text) / 2.54).rstrip('0').rstrip('.') if centimeterfield.text != "" else "0"
feetfield.text = str(float(centimeterfield.text) / 30.48).rstrip('0').rstrip('.') if centimeterfield.text != "" else "0"
yardfield.text = str(float(centimeterfield.text) / 91.44).rstrip('0').rstrip('.') if centimeterfield.text != "" else "0"
milefield.text = str(float(centimeterfield.text) / 160934).rstrip('0').rstrip('.') if centimeterfield.text != "" else "0"
MDTextField:
hint_text: "Meters"
id: meterfield
on_text:
millimeterfield.text = str(float(meterfield.text) * 1000).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
centimeterfield.text = str(float(meterfield.text) * 100).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
kilometerfield.text = str(float(meterfield.text) / 1000).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
inchfield.text = str(float(meterfield.text) * 39.37).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
feetfield.text = str(float(meterfield.text) * 3.281).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
yardfield.text = str(float(meterfield.text) * 1.094).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
milefield.text = str(float(meterfield.text) / 1609).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
MDTextField:
hint_text: "Kilometers"
id: kilometerfield
on_text:
millimeterfield.text = str(float(meterfield.text) * 1000).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
centimeterfield.text = str(float(meterfield.text) * 100).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
meterfield.text = str(float(meterfield.text) / 1000).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
inchfield.text = str(float(meterfield.text) * 39.37).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
feetfield.text = str(float(meterfield.text) * 3.281).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
yardfield.text = str(float(meterfield.text) * 1.094).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
milefield.text = str(float(meterfield.text) / 1609).rstrip('0').rstrip('.') if meterfield.text != "" else "0"
MDTextField:
hint_text: "Inches"
id: inchfield
on_text:
# ---- HERE WE CAN'T PUT ANY MORE CODE BECAUSE IT CRASHES THE APP IN THE PREVIOUS TEXT FIELD UPDATE ----
MDTextField:
hint_text: "Feet"
id: feetfield
MDTextField:
hint_text: "Yards"
id: yardfield
MDTextField:
hint_text: "Miles"
id: milefield
Thank you!
To be able to react to text changes by the user, not by code, the easiest solution is to subclass the
TextInput
(or in your caseMDTextInput
) and overrideinsert_text
.programmatic changes to text won't trigger this function.
As soon as this class has been loaded beforehand, you can use it in kvlang instead of
MDTextInput
, if you want to define it in another module without needing to import it, you can register it using Factory