Установить позицию курсора в TextInput - PullRequest
0 голосов
/ 25 августа 2018

Я использую Python 2.7 и KIVY.Когда я нажимаю за пределами Text в TextInput, я не могу печатать.Может ли кто-нибудь помочь мне, что когда я нажимаю textInput, как установить или сдвинуть cursor конец текста?Я использую instance.cursor = (len(instance.text), 0) в def on_focus() для установки положения курсора, но он не работает.

test.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.textinput import TextInput
from kivy.properties import BooleanProperty, ListProperty, ObjectProperty, NumericProperty, DictProperty, StringProperty
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (400, 50)

class RightFloatInput(TextInput):
    decimal = NumericProperty(0)
    negative = False

    def __init__(self, **kwargs):
        super(RightFloatInput, self).__init__(**kwargs)
        self.multiline = False

    def right_adjust(self, text):
        max_width = self.width - self.padding[0] - self.padding[2]

        new_text = text.strip()
        text_width = self._get_text_width(new_text, self.tab_width, self._label_cached)

        while text_width < max_width:
            new_text = ' ' + new_text
            text_width = self._get_text_width(new_text, self.tab_width, self._label_cached)

        while text_width >= max_width:
            if new_text != ' ':
                break
            else:
                new_text = new_text[1:]
                text_width = self._get_text_width(new_text, self.tab_width, self._label_cached)

        return new_text.rstrip()

    def on_size(self, instance, value):
        super(RightFloatInput, self).on_size(instance, value)
        if len(self._lines) == 0:
            return True
        cc, cr = self.cursor
        cur_text = self._lines[cr]
        initial_len = len(cur_text)
        super(RightFloatInput, self)._refresh_text(self.right_adjust(cur_text))
        final_len = len(self._lines[cr])
        self.cursor = self.get_cursor_from_index(final_len - (initial_len - cc))

        return

    def delete_selection(self, from_undo=False):
        # print('delete_selection')
        if not self._selection:
            return
        cr = self.cursor[1]
        initial_len = len(self._lines[cr])
        a, b = self._selection_from, self._selection_to
        if a > b:
            a, b = b, a
        super(RightFloatInput, self).delete_selection(from_undo=from_undo)
        cur_text = self._lines[cr]
        super(RightFloatInput, self)._refresh_text(self.right_adjust(cur_text))
        final_len = len(self._lines[cr])
        self.cursor = self.get_cursor_from_index(final_len - (initial_len - b))

    def do_backspace(self, from_undo=False, mode='bkspc'):
        # print('do_backspace')
        cc, cr = self.cursor
        initial_len = len(self._lines[cr])
        super(RightFloatInput, self).do_backspace(from_undo=from_undo, mode=mode)
        cc, cr = self.cursor
        cur_text = self._lines[cr]
        super(RightFloatInput, self)._refresh_text(self.right_adjust(cur_text))
        final_len = len(self._lines[cr])
        self.cursor = self.get_cursor_from_index(final_len - (initial_len - cc) + 1)

    def insert_text(self, the_text, from_undo=False):
        if self.readonly == True:
            return

        cc, cr = self.cursor
        cur_text = self._lines[cr]
        initial_len = len(cur_text)
        new_text = self.right_adjust(cur_text[:cc] + the_text + cur_text[cc:])

        try:
            if self.negative == True:
                if str(the_text) != "-":
                    num = float(new_text)  # throw exception if new_text is invalid float
            else:
                num = float(new_text)
        except ValueError:
            return

        if str(the_text) != "-":
            if num > 10000000:
                return

        self._lines[cr] = ''
        self._refresh_text(self.right_adjust(new_text))
        final_len = len(self._lines[cr])
        self.cursor = self.get_cursor_from_index(final_len - (initial_len - cc))

    def set_right_adj_text(self, text):
        self._refresh_text(self.right_adjust(text))

    def on_focus(self, instance, isFocused):
        if isFocused:
            final_len = len(instance.text)
            instance.cursor = self.get_cursor_from_index(final_len)
            Clock.schedule_once(lambda dt: self.selected_text())

        if instance.focus:
            self.cursor = (final_len, 0)
            print("TextInput is focused [focus={}]".format(instance.focus))
            instance.cursor = (len(instance.text), 0)
            Clock.schedule_once(lambda dt: instance.select_all())
            return
        else:
            try:
                num = float(self.text.strip())  # throw exception if new_text is invalid float
            except ValueError:
                return

            new_text = self.text.strip()
            new_text = self.right_adjust(new_text)
            self._refresh_text(new_text)
            final_len = len(new_text)
            self.cursor = self.get_cursor_from_index(final_len)

    def on_touch_down_2(self, instanse):
        final_len = len(self.text)
        self.cursor = self.get_cursor_from_index(final_len)
        return False

    def selected_text(self):
        ci = self.cursor_index()
        cc = self.cursor_col
        line = self._lines[self.cursor_row]
        len_line = len(line)
        start = max(0, len(line[:cc]) - line[:cc].rfind(u' ') - 1)
        end = line[cc:].find(u' ')
        end = end if end > - 1 else (len_line - cc)
        Clock.schedule_once(lambda dt: self.select_text(ci - start, ci + end))

    def on_text(self, instance, text):
        if text.count('-') > 1:
            self.text = "-"
            return

        new_text = self.right_adjust(text)

        self._refresh_text(new_text)

        final_len = len(new_text)
        self.cursor = self.get_cursor_from_index(final_len)

    def on_text_validate_old(self):
        try:
            num = float(self.text.strip())  # throw exception if new_text is invalid float
        except ValueError:
            return

        if self.decimal == 1 and self.text.strip() != "":
            self.text = str("{0:.1f}".format(float(self.text.strip())))

        if self.decimal == 2 and self.text.strip() != "":
            self.text = str("{0:.2f}".format(float(self.text.strip())))

        if self.decimal == 3 and self.text.strip() != "":
            self.text = str("{0:.3f}".format(float(self.text.strip())))

        new_text = self.right_adjust(self.text)
        self._refresh_text(new_text)
        final_len = len(new_text)
        self.cursor = self.get_cursor_from_index(final_len)


class abc(BoxLayout):
    pass

class Test(App):
    def build(self):
        return abc()


if __name__ == '__main__':
    Test().run()

test.kv

<abc>:
    BoxLayout:
        orientation: "vertical"
        size_hint_y: .5

        BoxLayout:
            orientation: "horizontal"
            spacing: 10, 10
            size_hint_x: .6

            Label:
                text: "TEXT"
                text_size: self.size
                valign: 'middle'
                size_hint_x: .2

            RightFloatInput:
                size_hint_x: .4
                text : "100"

1 Ответ

0 голосов
/ 25 августа 2018

TextInput - RightAlign

Добавить следующее:

  1. Заявление на импорт, from functools import partial
  2. Новый метод set_cursor()
  3. Clock.schedule_once (частичное (self.set_cursor, instance), 1)

Отрывок

from functools import partial
...
    def set_cursor(self, instance, dt):
        instance.cursor = (len(instance.text), 0)

    def on_focus(self, instance, isFocused):

        if instance.focus:
            final_len = len(instance.text)
            self.cursor = (final_len, 0)
            print("TextInput is focused [focus={}]".format(instance.focus))
            Clock.schedule_once(lambda dt: instance.select_all())
            Clock.schedule_once(partial(self.set_cursor, instance), 1)
            return
        else:
            try:
                num = float(self.text.strip())  # throw exception if new_text is invalid float
            except ValueError:
                return
            new_text = self.text.strip()
            new_text = self.right_adjust(new_text)
            self._refresh_text(new_text)
            final_len = len(new_text)
            self.cursor = self.get_cursor_from_index(final_len)

TextInput - LeftAlign

Чтобы установить курсор в конце текста, используйте instance.cursor = (len(instance.text), 0)

Отрывок

def on_focus(self, instance):
    if instance.focus:
        print("TextInput is focused [focus={}]".format(instance.focus))
        instance.cursor = (len(instance.text), 0)
        Clock.schedule_once(lambda dt: instance.select_all())
    else:
        print("TextInput is defocused [focus={}]".format(instance.focus))

Примечание

В документации Kivy есть опечатка. Курсор является кортежем (столбец, строка) , а не (ряд, столбец)

TextInput »курсор

cursor

Кортеж значений (row, col), указывающих текущую позицию курсора. Вы Можно установить новый (строка, столбец), если вы хотите переместить курсор. Прокрутка область будет автоматически обновлена, чтобы убедиться, что курсор виден внутри окна просмотра.

Курсором является AliasProperty.

...