0

我们正在编写一个作为转换器的应用程序。所以应用程序中有 8 个文本字段(来自 .kv 文件)。我们使用 on_text 参数相应地更新其他文本字段,但是当我们更新一定数量的字段时,它会循环运行并使用 RecursionError 使应用程序崩溃。问题是 on_text 参数不仅会在用户更改字段内的文本时执行其中的函数,而且还会在从代码更改文本参数时执行其中的函数。有没有办法只在用户更改它时运行它,无论它是键盘还是触摸屏,并且只在 KV 文件中而不需要任何额外的 python 代码?

这是给出问题的代码部分:

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

谢谢!

4

1 回答 1

0

为了能够对用户而不是代码的文本更改做出反应,最简单的解决方案是子类化TextInput(或在您的情况下MDTextInput)并覆盖insert_text

class CustomTextInput(MDTextInput):
    def insert_text(self, substring, from_undo=False):
         # do whatever you want to do here
         super().insert_text(substring, from_undo)
         # or there if you want to react after the normal change

对文本的编程更改不会触发此功能。

一旦这个类被预先加载,你可以在 kvlang 中使用它而不是MDTextInput,如果你想在另一个模块中定义它而不需要导入它,你可以使用工厂注册它

from kivy.factory import Factory

Factory.register('CusomTextInput', mod='python.path.to.module')
于 2021-09-26T20:04:15.063 回答