将光标位置设置为 TextInput

Set cursor position into TextInput

我正在使用 Python 2.7 和 kivy。
当我在 Text 之外单击进入 TextInput 时,我无法输入。 有人可以帮助我,当我点击 textInput 时,如何设置或移动文本的 cursor 结尾?
我在 def on_focus() 中使用 instance.cursor = (len(instance.text), 0) 来设置光标位置,但它不起作用。

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"

TextInput - 右对齐

添加以下内容:

  1. 导入语句,from functools import partial
  2. 新建一个方法set_cursor()
  3. Clock.schedule_once(部分(self.set_cursor, 实例), 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)

文本输入 - 左对齐

要将光标设置在文本末尾,请使用 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 文档中有错字。游标是 (col, row) 而不是 (row, col)[=18 的元组=]

TextInput » cursor

cursor

Tuple of (row, col) values indicating the current cursor position. You can set a new (row, col) if you want to move the cursor. The scrolling area will be automatically updated to ensure that the cursor is visible inside the viewport.

cursor is an AliasProperty.