Изменение размера и высоты textInput в кивах - PullRequest
0 голосов
/ 08 марта 2020
<AutoResizedText>
GridLayout:
    cols:1
    size: root.width, root.height
    TextInput:
        multiline:True
        size_hint:(None,None)
        size:(self.height,self.minimum_height )
        text: "hello my cat"

В настоящее время я пытаюсь получить TextInput, который увеличивается по ширине и высоте в зависимости от того, какая строка в нем содержится. Я смог заставить высоту расширяться вместе с текстом. Но не ширина по какой-то причине. self.minimum_width не является методом, когда я пытаюсь заменить self.height на self.minimum_height

1 Ответ

0 голосов
/ 08 марта 2020

TextInput не может делать то, что вы хотите, без каких-либо модификаций. Стандарт TextInput требует, чтобы вы установили ширину, затем он заполнит свое текстовое поле, разделив текст по мере необходимости, чтобы сохранить его на этой ширине, и вычислив на этом основании минимальную высоту.

Вот версия из TextInput, который я изменил, чтобы сделать то, что я думаю, что вы хотите:

class MyTextInput(TextInput):
    minimum_width = NumericProperty(0)

    def _split_smart(self, text):
        # modified to always split on newline only
        lines = text.split(u'\n')
        lines_flags = [0] + [FL_IS_LINEBREAK] * (len(lines) - 1)
        return lines, lines_flags

    def _refresh_text(self, text, *largs):
        # this is modified slightly just to calculate minimum_width

        # Refresh all the lines from a new text.
        # By using cache in internal functions, this method should be fast.
        mode = 'all'
        if len(largs) > 1:
            mode, start, finish, _lines, _lines_flags, len_lines = largs
            # start = max(0, start)
            cursor = None
        else:
            cursor = self.cursor_index()
            _lines, self._lines_flags = self._split_smart(text)
        _lines_labels = []
        _line_rects = []
        _create_label = self._create_line_label

        # calculate minimum width
        min_width = 0
        for x in _lines:
            lbl = _create_label(x)
            min_width = max(min_width, lbl.width)
            _lines_labels.append(lbl)
            _line_rects.append(Rectangle(size=lbl.size))
        self.minimum_width = min_width + self.padding[0] + self.padding[2]

        if mode == 'all':
            self._lines_labels = _lines_labels
            self._lines_rects = _line_rects
            self._lines = _lines
        elif mode == 'del':
            if finish > start:
                self._insert_lines(start,
                                   finish if start == finish else (finish + 1),
                                   len_lines, _lines_flags,
                                   _lines, _lines_labels, _line_rects)
        elif mode == 'insert':
            self._insert_lines(
                start,
                finish if (start == finish and not len_lines)
                else (finish + 1),
                len_lines, _lines_flags, _lines, _lines_labels,
                _line_rects)

        min_line_ht = self._label_cached.get_extents('_')[1]
        # with markup texture can be of height `1`
        self.line_height = max(_lines_labels[0].height, min_line_ht)
        # self.line_spacing = 2
        # now, if the text change, maybe the cursor is not at the same place as
        # before. so, try to set the cursor on the good place
        row = self.cursor_row
        self.cursor = self.get_cursor_from_index(self.cursor_index()
                                                 if cursor is None else cursor)
        # if we back to a new line, reset the scroll, otherwise, the effect is
        # ugly
        if self.cursor_row != row:
            self.scroll_x = 0
        # with the new text don't forget to update graphics again
        self._trigger_update_graphics()

    def on_text(self, *args):
        # added to update minimum width on each change
        cc, cr = self.cursor
        text = self._lines[cr]
        lbl = self._create_line_label(text)
        self.minimum_width = max(self.minimum_width, lbl.width + self.padding[0] + self.padding[2])

Эта версия TextInput имеет свойство minimum_width. Я изменил _smart_split(), чтобы он разделял только строки на новые строки. _refresh_text() почти идентичен оригиналу, но включает вычисление minimum_width. Я добавил on_text() метод для обновления minimum_width каждый раз, когда text изменяется. Итак, теперь вы можете использовать self.minimum_width и self.minimum_height для определения размера Widget как:

MyTextInput:
    multiline: True
    size_hint:(None,None)
    size:(self.minimum_width, self.minimum_height)
    text: "hello my cat"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...