Переместите курсор в конечную позицию строки в MDTextField

Я пытаюсь указать формат даты для MDTextField в приложении, которое я разрабатываю с KivyMD. Формат такого поля: «дд/мм/гггг».

Что я пытаюсь сделать, так это то, что после того, как первые 2 числа будут написаны, «/» будет записано автоматически, и курсор переместится на последнюю позицию справа от «/» (например, «21/»). Таким же образом, после записи двух других цифр после первой «/», будет написана вторая «/», и курсор снова переместится в конец (например, «21/09/»).

Мне удалось отобразить оба символа «/», тем не менее, это курсор, который я не могу поместить в нужное место. Мой код следующий:

def apply_date_format(self):
    # delete '/' if len is equal or less than 2 and final character is /  
    if len(self.ids.viajeInicio.text) =< 2 and (self.ids.viajeInicio.text).endswith('/'):
        self.ids.viajeInicio.text = (self.ids.viajeInicio.text[:-1])
    # first '/'
    elif len(self.ids.viajeInicio.text) == 2 and (self.ids.viajeInicio.text).isnumeric():
        self.ids.viajeInicio.text= self.ids.viajeInicio.text + "/"
    # second '/'
    elif len(self.ids.viajeInicio.text) == 5 and (self.ids.viajeInicio.text[3:5]).isnumeric():
        self.ids.viajeInicio.text= self.ids.viajeInicio.text + "/"
    # delete last '/' if len is <= 5 and last character is '/'
    elif len(self.ids.viajeInicio.text) > 3 and len(self.ids.viajeInicio.text) <= 5 \
             and (self.ids.viajeInicio.text).endswith('/'):
        self.ids.viajeInicio.text = (self.ids.viajeInicio.text[:-1])

MDTextField имеет идентификатор viajeInicio, а функция apply_date_format вызывается для события on_text. Код следующий:

MDTextField:
    id: viajeInicio
    hint_text: 'Ingresar Fecha de Inicio del Viaje'
    pos_hint: {"x":0, "top":1}
    helper_text: 'Formato de fecha: dd/mm/aaaa'
    helper_text_mode: 'on_focus'
    required: True
    on_text:
        root.apply_date_format()

Как я могу переместить позицию курсора в конец строки после записи «/». Более того, есть ли лучший способ выполнить желаемую задачу?

Заранее большое спасибо


person Diego Gc    schedule 21.09.2020    source источник


Ответы (1)


Я думаю, что проще просто расширить класс MDTextField и переопределить его метод insert_text(). Что-то вроде этого:

class DateMDTextField(MDTextField):
    def insert_text(self, the_text, from_undo=False):
        if the_text == '/':
            # do not allow typed in '/'
            return
        cc, cr = self.cursor
        cur_text = self._lines[cr] + the_text  # existing text plus the to be inserted the_text
        cur_len = len(cur_text)

        # new_text will be inserted. The default is to just use the_text
        new_text = the_text

        # delete '/' if len is equal or less than 2 and final character is /
        if cur_len <= 2 and cur_text.endswith('/'):
            new_text = new_text[:-1]
        # first '/'
        elif cur_len == 2 and cur_text.isnumeric():
            new_text += '/'
        # second '/'
        elif cur_len == 5 and cur_text[3:5].isnumeric():
            new_text += '/'
        # delete last '/' if len is <= 5 and last character is '/'
        elif cur_len > 3 and cur_len <= 5 and cur_text.endswith('/'):
            new_text = new_text[:-1]
        # do not allow extra characters
        elif cur_len > 10:
            return

        # call the insert_text() of the MDTextField with the possibly modified text
        super(DateMDTextField, self).insert_text(new_text, from_undo=from_undo)

Приведенный выше код использует вашу логику (с парой небольших дополнений), и, поскольку он просто вызывает insert_text() из MDTextField, все движения курсора обрабатываются за вас.

Итак, вы можете просто заменить:

MDTextField:
    id: viajeInicio
    hint_text: 'Ingresar Fecha de Inicio del Viaje'
    pos_hint: {"x":0, "top":1}
    helper_text: 'Formato de fecha: dd/mm/aaaa'
    helper_text_mode: 'on_focus'
    required: True
    on_text:
        root.apply_date_format()

с:

DateMDTextField:
    id: viajeInicio
    hint_text: 'Ingresar Fecha de Inicio del Viaje'
    pos_hint: {"x":0, "top":1}
    helper_text: 'Formato de fecha: dd/mm/aaaa'
    helper_text_mode: 'on_focus'
    required: True

в вашем "кв". Вам не нужно явно вызывать метод insert_text(), так как он автоматически вызывается базовым классом TextInput. И вам также не нужна запись on_text.

И вам больше не нужен метод apply_date_format().

person John Anderson    schedule 22.09.2020
comment
Большое спасибо за ваш ответ Джон. У меня есть еще один вопрос к вам. Как мне вызвать этот класс из моего KV-файла? В моей предыдущей попытке у меня была моя функция внутри класса, которая относится к конкретному желаемому экрану. Поэтому я использовал root.my_function(). Как я могу вызывать функции из других классов Kivy? Заранее большое спасибо. - person Diego Gc; 22.09.2020
comment
Я попытался со следующим кодом: code def apply_date_format(self): DateMDTextField.insert_text(self.ids.viajeFinal, self.ids.viajeFinal.text) code Мне удалось запустить программу, тем не менее она привела к нежелательным результатам. Если я наберу только 1 число (например, «2»), TextField автоматически обновится до «2/22/2». - person Diego Gc; 22.09.2020