Kivy Python: обнаружение возврата в текстовом вводе - PullRequest
0 голосов
/ 29 июня 2018

Я пытаюсь создать простой TextInput для дат, который ограничивает ввод цифрами и автоматически заполняет косую черту для формата (мм / дд / гг). Мне удалось создать фильтр, который делает это путем переопределения 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)

Ответы [ 3 ]

0 голосов
/ 01 июля 2018

Вот полное решение для тех, кто хочет автоматически отформатировать ввод даты:

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)
0 голосов
/ 10 июля 2018

Решение

Переопределить метод do_backspace() в TextInput. Если текст «/», верните True, что означает, что мы использовали обратное пространство и не хотим, чтобы оно распространялось дальше.

Наконец, если текст не '/', мы вызываем исходное событие, используя super (…), и возвращаем результат. Это позволяет продолжить распространение события do_backspace, как это обычно и происходит.

Подробнее см. В примере.

Ввод текста »Метод do_backspace ()

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

выход

Img01 Img02

0 голосов
/ 29 июня 2018

Начиная с версии 1.9.0 TextInput присущ FocusBehavior, поэтому, если вы хотите определить, когда вы нажимаете клавишу возврата, вы должны использовать 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()
...