将光标位置设置为 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 - 右对齐
添加以下内容:
- 导入语句,
from functools import partial
- 新建一个方法
set_cursor()
- 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 的元组=]
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.
我正在使用 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 - 右对齐
添加以下内容:
- 导入语句,
from functools import partial
- 新建一个方法
set_cursor()
- 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 的元组=]
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.