【问题标题】:Kivy Python: Detect backspace in Text InputKivy Python:检测文本输入中的退格
【发布时间】:2018-12-08 04:12:09
【问题描述】:

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

这是一个解释我想要做什么的 sn-p,但 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)

【问题讨论】:

    标签: python kivy detection keystroke backspace


    【解决方案1】:

    这是我的解决方案:

    class DateInput(TextInput):
        pat = re.compile("[^0-9]")
    
        def insert_text(self, substring, from_undo=False):
            pat = self.pat
            s = re.sub(pat, "", substring)
            if len(self.text) >= 10:
                return super(DateInput, self).insert_text("", from_undo=from_undo)
            elif ((len(self.text) > 2) and (self.cursor_index() == 2)) or (
                (len(self.text) > 5) and (self.cursor_index() == 5)
            ):
                return super(DateInput, self).insert_text("/", from_undo=from_undo)
            elif (len(self.text) == 2) or (len(self.text) == 5):
                return super(DateInput, self).insert_text("/" + s, from_undo=from_undo)
            else:
                return super(DateInput, self).insert_text(s, from_undo=from_undo)
    

    【讨论】:

      【解决方案2】:

      解决方案

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

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

      详情请参考示例。

      Text Input » do_backspace() method

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

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

      • 删除当前选择(如果有)。
      • 删除前一个字符并将光标向后移动。
      • 如果我们一开始就什么也不做。

      示例

      main.py

      ​​>
      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()
      

      输出

      【讨论】:

        【解决方案3】:

        由于版本 1.9.0 TextInputFocusBehavior 所固有的,因此如果您想检测何时按下退格键,您必须使用 keyboard_on_key_down() 方法或 keyboard_on_key_up() 方法:

        from kivy.app import App
        from kivy.uix.textinput import TextInput
        
        class DateInput(TextInput):
            def keyboard_on_key_down(self, window, keycode, text, modifiers):
                if keycode[1] == "backspace":
                    print("print backspace down", keycode)
                TextInput.keyboard_on_key_down(self, window, keycode, text, modifiers)
        
            def keyboard_on_key_up(self, window, keycode, text, modifiers):
                if keycode[1] == "backspace":
                    print("print backspace up", keycode)
                TextInput.keyboard_on_key_down(self, window, keycode, text, modifiers)
        
        
        class MyApp(App):
            def build(self):
                return DateInput()
        
        if __name__ == '__main__':
            MyApp().run()
        

        【讨论】:

        • 太棒了!这非常有帮助。我将使用keyboard_on_key_up(self, window, keycode) 将其切换出来,以防止在用户完成退格之前运行代码。谢谢!
        【解决方案4】:

        以下是任何想要自动格式化日期输入的人的完整解决方案:

        class DateInput(TextInput):
            def keyboard_on_key_up(self, window, keycode):
                if keycode[1] == "backspace" and len(self.text) >= 1:
                    if self.text[-1] == "/":
                        self.text = self.text[:-1]
                    else:
                        pass
                else:
                    pass
                TextInput.keyboard_on_key_up(self, window, keycode)
        
            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) == 2:
                    s = re.sub(pat, '', substring)
                    if s != '':
                        s = '/' + s
                elif len(self.text) == 5:
                    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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多