首页 > 解决方案 > Kivy Python:检测文本输入中的退格

问题描述

我正在尝试为日期创建一个简单的 TextInput,将输入限制为数字并自动填充 (mm/dd/yy) 格式的正斜杠。我通过重新定义 insert_text() 成功创建了一个过滤器,除了用户退格时,我还想自动删除斜杠。但是我不知道如何检测用户何时在文本输入中退格,以便我可以在必要时触发一个事件来擦除斜杠。

这是一个解释我想要做什么的片段,但 TextInput 没有“on_key_up”属性。有没有办法添加一个?或者更好的方法来解决这个问题?

# .kv file

<DateInput>
    on_key_up: self.check_for_backspace(keycode) # not a true attribute

# .py file

class DateInput(TextInput):

    # checks if last character is a slash and removes it after backspace keystroke.  Not sure this would work.
    def check_for_backspace(self, keycode):
        if keycode[1] == 'backspace' and self.text[-1:] == '/':
            self.text = self.text[:-1]

    #filter for date formatting which works well aside from backspacing
    pat = re.compile('[^0-9]')
    def insert_text(self, substring, from_undo=False):
        pat = self.pat
        if len(substring) > 1:
            substring = re.sub(pat, '', (self.text + substring))
            self.text = ''
            slen = len(substring)
            if slen == 2:
                s = substring[:2] + '/'
            elif slen == 3:
                s = substring[:2] + '/' + substring[2:]
            elif slen == 4:
                s = substring[:2] + '/' + substring[2:] + '/'
            else:
                s = substring[:2] + '/' + substring[2:4] + '/' + substring[4:8]
        elif len(self.text) > 9:
            s = ''
        elif len(self.text) == 1:
            s = re.sub(pat, '', substring)
            if s != '':
                s = s + '/'
        elif len(self.text) == 4:
            s = re.sub(pat, '', substring)
            if s != '':
                s = s + '/'
        else:
            s = re.sub(pat, '', substring)
        return super(DateInput, self).insert_text(s, from_undo=from_undo)

标签: pythonkivydetectionkeystrokebackspace

解决方案


解决方案

覆盖do_backspace()TextInput 中的方法。如果文本是 '/' 则返回 True,表示我们已经消耗了退格并且不希望它进一步传播。

最后,如果文本不是 '/',我们使用 super(...) 调用原始事件并返回结果。这允许 do_backspace 事件传播继续正常发生。

详情请参阅示例。

文本输入 » do_backspace() 方法

do_backspace(from_undo=False, mode='bkspc')

从当前光标位置执行退格操作。此操作可能会做几件事:

  • 如果可用,删除当前选择。
  • 删除前一个字符并将光标移回。
  • 什么都不做,如果我们在开始的话。

例子

主文件

from kivy.app import App
from kivy.uix.textinput import TextInput
import re


class DateInput(TextInput):

    def do_backspace(self, from_undo=False, mode='bkspc'):
        print(from_undo, mode)
        if len(self.text) >= 1:
            if self.text[-1] == "/":
                self.text = self.text[:-1]
                return True    # we have consumed the backspace and don’t want it to propagate any further
        return super(DateInput, self).do_backspace(from_undo, mode)

    #filter for date formatting which works well aside from backspacing
    pat = re.compile('[^0-9]')

    def insert_text(self, substring, from_undo=False):
        pat = self.pat
        if len(substring) > 1:
            substring = re.sub(pat, '', (self.text + substring))
            self.text = ''
            slen = len(substring)
            if slen == 2:
                s = substring[:2] + '/'
            elif slen == 3:
                s = substring[:2] + '/' + substring[2:]
            elif slen == 4:
                s = substring[:2] + '/' + substring[2:] + '/'
            else:
                s = substring[:2] + '/' + substring[2:4] + '/' + substring[4:8]
        elif len(self.text) > 9:
            s = ''
        elif len(self.text) == 1:
            s = re.sub(pat, '', substring)
            if s != '':
                s = s + '/'
        elif len(self.text) == 4:
            s = re.sub(pat, '', substring)
            if s != '':
                s = s + '/'
        else:
            s = re.sub(pat, '', substring)
        return super(DateInput, self).insert_text(s, from_undo=from_undo)


class TestApp(App):

    def build(self):
        return DateInput()


if __name__ == "__main__":
    TestApp().run()

输出

图像01 图像02


推荐阅读