【问题标题】:Kivy : How to start text from right side in TextInput?Kivy:如何在 TextInput 中从右侧开始文本?
【发布时间】:2018-03-14 12:22:26
【问题描述】:

当我输入 MyFloatInput TextInput 时,文本从 TextInput 的 right 一侧开始,它运行良好
但我从.py 设置了MyFloatInput TextInput 的值,然后它从左侧开始。它不会显示在右侧。
有人可以告诉我代码有什么问题吗?

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

【问题讨论】:

  • Python-xxx 标记仅应在代码涉及仅适用于特定版本的问题或要求时使用

标签: python python-2.7 kivy kivy-language


【解决方案1】:

我不知道使用TextInput 可用选项的任何方法。但可以通过扩展TextInput 来完成。这是一个MyFloatInput 类:

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 类得到更新,代码可能会中断。

【讨论】:

  • @macsontaylor 将super() 更改为super(MyFloatInput, self) 应该可以在python2 中运行,在python2 中运行有什么问题?
  • @macsontaylor import string
【解决方案2】:

我对@9​​87654321@ 类进行了重大更改。它现在不再需要 string 导入。它现在处理删除选择,您现在可以使用 set_right_adj_text("some text") 方法从 .py 文件中设置文本。这是改进的类:

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))

【讨论】:

  • 谢谢。我更新了代码。当增加TextInput 的大小和从.py 文件传递​​的值时,它不会显示右对齐,而是显示在中心
  • 我添加了一个on_size() 方法来处理大小变化。它反映在上面的编辑代码中
  • “打字不正常”是什么意思?它对我来说似乎工作正常。
猜你喜欢
  • 2019-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-05
  • 2016-07-11
  • 2021-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多