I am trying to give a date format to a MDTextField on an app I am developing with KivyMD. The format of such field such be 'dd/mm/yyyy'.
What I am trying to do is that once the first 2 numbers are written, a '/' will be written automatically and the cursor will jump to the last position, right of the '/' (e.g. '21/'). In the same manner, after writting other 2 numbers after the first '/', a second '/' will be written and the cursor will move to the end again (e.g. '21/09/').
I have managed to make both '/' appear, nevertheless, it is the cursor I am unable to place on the desired location. My code is the following:
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])
The MDTextField has the id viajeInicio and the function apply_date_format is called on the on_text event. The code is the following:
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()
How can I move the cursor position to the end of the string after the '/' are written. Moreover, is there a better way to complete the desired task?
Thanks a lot in advance
I think it is simpler to just extend the MDTextField
class and over-ride it's insert_text()
method. Something like this:
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)
The above code uses your logic (with a couple small additions), and since it just ends up calling the insert_text()
of the MDTextField
, all the cursor movement is handled for you.
So you can just replace:
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()
with:
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
in your 'kv'. You do not need to explicitly call the insert_text()
method as it is automatically called by the baseclass TextInput
. And you also do not need the on_text
entry.
And you no longer need the apply_date_format()
method.