Kivy:如何在 TextInput 中从右侧开始文本?
Kivy : How to start text from right side in TextInput?
当我输入 MyFloatInput
TextInput 时,文本从 TextInput 的 right
一侧开始,它工作完美
但是我从 .py
设置了 MyFloatInput
TextInput 的值然后它从左边开始 side.It 不显示在右边。
有人可以告诉我代码有什么问题吗?
test.py
import kivy
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.textinput import TextInput
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (400, 100)
class MyFloatInput(TextInput):
def __init__(self, **kwargs):
super(MyFloatInput, self).__init__(**kwargs)
self.multiline = False
def right_adjust(self, text):
max_width = self.width - self.padding[0] - self.padding[2]
new_text = text
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[0] != ' ':
break
else:
new_text = new_text[1:]
text_width = self._get_text_width(new_text, self.tab_width, self._label_cached)
return new_text
def delete_selection(self, from_undo=False):
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(MyFloatInput, self).delete_selection(from_undo=from_undo)
cur_text = self._lines[cr]
super(MyFloatInput, 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'):
cc, cr = self.cursor
initial_len = len(self._lines[cr])
super(MyFloatInput, self).do_backspace(from_undo=from_undo, mode=mode)
cc, cr = self.cursor
cur_text = self._lines[cr]
super(MyFloatInput, 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):
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:
num = float(new_text) # throw exception if new_text is invalid float
except ValueError:
return
self._lines[cr] = ''
super(MyFloatInput, self).insert_text(new_text, from_undo=from_undo)
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):
num = float(text) # throws exception if text is invalid float
self._refresh_text(self.right_adjust(text))
def on_text(self, instance, text):
#num = float(text) # throws exception if text is invalid float
self._refresh_text(self.right_adjust(text))
class Testing(Screen):
def __init__(self, **kwargs):
super(Testing, self).__init__(**kwargs)
Clock.schedule_once(lambda dt: setattr(self.test, 'text', str(100)))
class Test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
Test().run()
test.kv
Testing:
test:test
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
padding: 10, 10
spacing: 10, 10
size_hint_x: .6
Label:
text: "No."
text_size: self.size
valign: 'middle'
size_hint_x: .2
MyFloatInput:
size_hint_x: .6
id : test
我不知道有什么方法可以使用 TextInput
可用的选项。但是可以通过扩展TextInput
来完成。这是一个 MyFloatInput
class:
import string
class MyFloatInput(TextInput):
def __init__(self, **kwargs):
super(MyFloatInput, self).__init__(**kwargs)
self.multiline = False
def insert_text(self, theText, from_undo=False):
if theText not in string.digits and theText != '.':
return
if '.' in self.text and theText == '.':
return
maxWidth = self.width - self.padding[0] - self.padding[2]
cc, cr = self.cursor
curText = self._lines[cr]
new_text = curText[:cc] + theText + curText[cc:]
textWidth = self._get_text_width(new_text, self.tab_width, self._label_cached)
while textWidth < maxWidth:
new_text = ' ' + new_text
textWidth = self._get_text_width(new_text, self.tab_width, self._label_cached)
while textWidth >= maxWidth:
if new_text[0] != ' ':
break
else:
new_text = new_text[1:]
textWidth = self._get_text_width(new_text, self.tab_width, self._label_cached)
self._lines[cr] = ''
self.cursor = (0,cr)
super(MyFloatInput, self).insert_text(new_text, from_undo=from_undo)
这应该会做你想做的事并且也会做 float
过滤。要使用它,请将其包含在您的 .py 文件中并将 .kv 文件的 TextInput
部分替换为:
MyFloatInput:
size_hint_x: .2
请注意,这仅适用于单行输入,因此 __init__
方法将 multiline
设置为 False
。此代码使用以 _
开头的方法和变量,因此如果更新 TextInput
class,代码可能会中断。
我对 MyFloatInput
class 进行了重大更改。它现在不再需要 string
导入。它现在处理删除选择,您现在可以使用 set_right_adj_text("some text")
方法从 .py 文件设置文本。这是改进后的 class:
class MyFloatInput(TextInput):
def __init__(self, **kwargs):
super(MyFloatInput, self).__init__(**kwargs)
self.multiline = False
def right_adjust(self, text):
max_width = self.width - self.padding[0] - self.padding[2]
new_text = text
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[0] != ' ':
break
else:
new_text = new_text[1:]
text_width = self._get_text_width(new_text, self.tab_width, self._label_cached)
return new_text
def on_size(self, instance, value):
super(MyFloatInput, 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(MyFloatInput, 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 True
def delete_selection(self, from_undo=False):
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(MyFloatInput, self).delete_selection(from_undo=from_undo)
cur_text = self._lines[cr]
super(MyFloatInput, 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'):
cc, cr = self.cursor
initial_len = len(self._lines[cr])
super(MyFloatInput, self).do_backspace(from_undo=from_undo, mode=mode)
cc, cr = self.cursor
cur_text = self._lines[cr]
super(MyFloatInput, 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):
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:
num = float(new_text) # throw exception if new_text is invalid float
except ValueError:
return
self._lines[cr] = ''
super(MyFloatInput, self).insert_text(new_text, from_undo=from_undo)
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):
num = float(text) # throws exception if text is invalid float
self._refresh_text(self.right_adjust(text))
当我输入 MyFloatInput
TextInput 时,文本从 TextInput 的 right
一侧开始,它工作完美
但是我从 .py
设置了 MyFloatInput
TextInput 的值然后它从左边开始 side.It 不显示在右边。
有人可以告诉我代码有什么问题吗?
test.py
import kivy
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.textinput import TextInput
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (400, 100)
class MyFloatInput(TextInput):
def __init__(self, **kwargs):
super(MyFloatInput, self).__init__(**kwargs)
self.multiline = False
def right_adjust(self, text):
max_width = self.width - self.padding[0] - self.padding[2]
new_text = text
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[0] != ' ':
break
else:
new_text = new_text[1:]
text_width = self._get_text_width(new_text, self.tab_width, self._label_cached)
return new_text
def delete_selection(self, from_undo=False):
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(MyFloatInput, self).delete_selection(from_undo=from_undo)
cur_text = self._lines[cr]
super(MyFloatInput, 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'):
cc, cr = self.cursor
initial_len = len(self._lines[cr])
super(MyFloatInput, self).do_backspace(from_undo=from_undo, mode=mode)
cc, cr = self.cursor
cur_text = self._lines[cr]
super(MyFloatInput, 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):
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:
num = float(new_text) # throw exception if new_text is invalid float
except ValueError:
return
self._lines[cr] = ''
super(MyFloatInput, self).insert_text(new_text, from_undo=from_undo)
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):
num = float(text) # throws exception if text is invalid float
self._refresh_text(self.right_adjust(text))
def on_text(self, instance, text):
#num = float(text) # throws exception if text is invalid float
self._refresh_text(self.right_adjust(text))
class Testing(Screen):
def __init__(self, **kwargs):
super(Testing, self).__init__(**kwargs)
Clock.schedule_once(lambda dt: setattr(self.test, 'text', str(100)))
class Test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
Test().run()
test.kv
Testing:
test:test
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
padding: 10, 10
spacing: 10, 10
size_hint_x: .6
Label:
text: "No."
text_size: self.size
valign: 'middle'
size_hint_x: .2
MyFloatInput:
size_hint_x: .6
id : test
我不知道有什么方法可以使用 TextInput
可用的选项。但是可以通过扩展TextInput
来完成。这是一个 MyFloatInput
class:
import string
class MyFloatInput(TextInput):
def __init__(self, **kwargs):
super(MyFloatInput, self).__init__(**kwargs)
self.multiline = False
def insert_text(self, theText, from_undo=False):
if theText not in string.digits and theText != '.':
return
if '.' in self.text and theText == '.':
return
maxWidth = self.width - self.padding[0] - self.padding[2]
cc, cr = self.cursor
curText = self._lines[cr]
new_text = curText[:cc] + theText + curText[cc:]
textWidth = self._get_text_width(new_text, self.tab_width, self._label_cached)
while textWidth < maxWidth:
new_text = ' ' + new_text
textWidth = self._get_text_width(new_text, self.tab_width, self._label_cached)
while textWidth >= maxWidth:
if new_text[0] != ' ':
break
else:
new_text = new_text[1:]
textWidth = self._get_text_width(new_text, self.tab_width, self._label_cached)
self._lines[cr] = ''
self.cursor = (0,cr)
super(MyFloatInput, self).insert_text(new_text, from_undo=from_undo)
这应该会做你想做的事并且也会做 float
过滤。要使用它,请将其包含在您的 .py 文件中并将 .kv 文件的 TextInput
部分替换为:
MyFloatInput:
size_hint_x: .2
请注意,这仅适用于单行输入,因此 __init__
方法将 multiline
设置为 False
。此代码使用以 _
开头的方法和变量,因此如果更新 TextInput
class,代码可能会中断。
我对 MyFloatInput
class 进行了重大更改。它现在不再需要 string
导入。它现在处理删除选择,您现在可以使用 set_right_adj_text("some text")
方法从 .py 文件设置文本。这是改进后的 class:
class MyFloatInput(TextInput):
def __init__(self, **kwargs):
super(MyFloatInput, self).__init__(**kwargs)
self.multiline = False
def right_adjust(self, text):
max_width = self.width - self.padding[0] - self.padding[2]
new_text = text
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[0] != ' ':
break
else:
new_text = new_text[1:]
text_width = self._get_text_width(new_text, self.tab_width, self._label_cached)
return new_text
def on_size(self, instance, value):
super(MyFloatInput, 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(MyFloatInput, 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 True
def delete_selection(self, from_undo=False):
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(MyFloatInput, self).delete_selection(from_undo=from_undo)
cur_text = self._lines[cr]
super(MyFloatInput, 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'):
cc, cr = self.cursor
initial_len = len(self._lines[cr])
super(MyFloatInput, self).do_backspace(from_undo=from_undo, mode=mode)
cc, cr = self.cursor
cur_text = self._lines[cr]
super(MyFloatInput, 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):
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:
num = float(new_text) # throw exception if new_text is invalid float
except ValueError:
return
self._lines[cr] = ''
super(MyFloatInput, self).insert_text(new_text, from_undo=from_undo)
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):
num = float(text) # throws exception if text is invalid float
self._refresh_text(self.right_adjust(text))