将光标位置设置为TextInput

时间:2018-08-25 11:38:47

标签: python kivy kivy-language

我正在使用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 :(得分:3)

TextInput-RightAlign

添加以下内容:

  1. 导入语句,from functools import partial
  2. 新方法set_cursor()
  3. Clock.schedule_once(partial(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

cursor
     

(行,列)值的元组,指示当前光标位置。您   如果要移动光标,可以设置一个新的(行,列)。滚动   区域将自动更新以确保光标位于   在视口中可见。

     

光标是AliasProperty。