【问题标题】:Kivy - Limit Values on InputTextKivy - InputText 上的限制值
【发布时间】:2018-06-29 01:50:10
【问题描述】:

我正在尝试制作只接受浮点值的输入文本。此外,输入的值必须介于两个值之间。

我创建了一个包含“验证”方法的类。如果值不在两个值之间,则会显示一个弹出窗口。

但我有一个问题。该方法仅在用户点击“Enter”时调用。我尝试在文本更改时调用该方法,但这对用户来说很烦人,因为在用户输入数据时会一直出现弹出窗口。

还有其他方法可以做这样的事情吗?

Python 文件:

class BoundedInput(BoxLayout):
    value = NumericProperty()

    def validate(self, min_value, max_value):
        status = min_value <= self.value <= max_value
        if not status:
            message = f'Value must be between {min_value} and {max_value}'
            popup = Popup(title='Warning', content=Label(text=message),
                            size_hint=(None, None), size=(300, 200))
            popup.open()

Kv 文件:

<NumericInput@TextInput>:
    input_filter: 'float'
    multiline: False

<BoundedInput>:
    orientation: 'horizontal'
    Label:
        text: 'Value'
    NumericInput:
        text: str(root.value)
        on_text_validate:
            root.value = float(self.text)
            root.validate(5, 100)

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    一个合适的方法可以是过滤,除了浮动它也在范围内我们创建一个继承TextInput的类并覆盖insert_text方法:

    from kivy.app import App
    from kivy.base import Builder
    from kivy.properties import NumericProperty
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.textinput import TextInput
    
    
    Builder.load_string("""
    <BoundedLayout>:
        orientation: 'horizontal'
        Label:
            text: 'Value'
        NumericInput:
            min_value : 5
            max_value : 100
            hint_text : 'Enter values between {} and {}'.format(self.min_value, self.max_value)
    """)
    
    class NumericInput(TextInput):
        min_value = NumericProperty()
        max_value = NumericProperty()
        def __init__(self, *args, **kwargs):
            TextInput.__init__(self, *args, **kwargs)
            self.input_filter = 'float'
            self.multiline = False
    
        def insert_text(self, string, from_undo=False):
            new_text = self.text + string
            if new_text != "":
                if self.min_value <= float(new_text) <= self.max_value:
                    TextInput.insert_text(self, string, from_undo=from_undo)
    
    class BoundedLayout(BoxLayout):
        pass
    
    class MyApp(App):
        def build(self):
            return BoundedLayout()
    
    if __name__ == '__main__':
        MyApp().run()
    

    【讨论】:

    • 这是一个好方法。唯一的问题是用户不知道为什么他们不能输入一些值。我在 input_text 中添加了一个“hint_text”来通知用户最小值和最大值。谢谢!
    • @Eduardo 当然,这补充了我的解决方案。
    • @Eduardo 我已经添加了它,如果我的回答对您有帮助,您可以将其标记为正确。 :D
    • 我发现了一个问题,例如我不能从一开始就输入“100”。我会调查如何解决它。
    • 如果我错了,请纠正我,但这个验证不是假设正在附加子字符串吗?如果新文本插入现有文本的中间会怎样,即 3.90 -> 39.90 将检查 3.909 是否在范围内...
    【解决方案2】:

    您可以使用Bubble,只要输入错误就让它挂起。
    您甚至可以编辑标签以找出问题所在。
    或更改文本颜色(如果验证与否)。
    我做了一个例子,两者都实现了。

    from kivy.app import App
    from kivy.uix.textinput import TextInput
    from kivy.uix.bubble import Bubble
    from kivy.lang import Builder
    from kivy.uix.floatlayout import FloatLayout
    from kivy.properties import BooleanProperty
    
    KV = """
    
    <ValidateLabel>:
        size_hint: (None, None)
        size: (280, 60)
        Label:
            id: label
            text: "Must be a float"
    
    
    <MyInput>:
        foreground_color: (0,1,0,1) if root.validated else (1,0,0,1)
    
    
    FloatInput:
    
    """
    
    
    class MyInput(TextInput):
        validated = BooleanProperty(False)
    
    
    class FloatInput(FloatLayout):
        bubble_showed = True
    
        def __init__(self, **kwargs):
            super(FloatInput, self).__init__(**kwargs)
            self.input = MyInput()
            self.input.bind(text=self.validate)
            self.add_widget(self.input)
            self.bubble = ValidateLabel()
            self.add_widget(self.bubble)
    
        def validate(self, input, value, min_value=15., max_value=25.):
            self.bubble.ids.label.text = "Number must be between {} and {}".format(min_value, max_value)
            try:
                print(min_value, max_value)
                status = float(min_value) <= float(value) <= float(max_value)
            except Exception as e:
                status = False
                self.bubble.ids.label.text = "Input must be a number"
    
            if not status:
                if not self.bubble_showed:
                    self.input.validated = False
                    self.add_widget(self.bubble)
                    self.bubble_showed = True
            else:
                print("bubble removed")
                self.input.validated = True
                self.remove_widget(self.bubble)
                self.bubble_showed = False
    
    
    class ValidateLabel(Bubble):
        validated = False
    
    
    class TestApp(App):
    
        def build(self):
            return Builder.load_string(KV)
    
    
    TestApp().run()
    

    输出:

    数字变小或大:

    号码没问题:

    输入值不是数字:

    【讨论】:

    • 这是一个好方法。及时通知用户。我会试试看,我会带着 cmets 回来。
    • @Eduardo 是的,在我看来,这些至少有两种方式可以很好地结合在一起。绿色表示没问题,就不需要泡了。祝你好运。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    相关资源
    最近更新 更多