Kivy: Контроль высоты метки без текстуры - PullRequest
0 голосов
/ 22 сентября 2019

проблема
У меня есть ярлык, высота которого привязана к высоте текстуры внутри него.К сожалению, если в метке нет текста, текстуры нет, а высота установлена ​​равной 0.

для пользовательского класса
Метка - это пользовательский класс с именем StretchingLabel.Его высота увеличивается или уменьшается в соответствии с объемом текста.Но если пользователь дважды щелкает ярлык, появляется символ TextInput того же размера, который позволяет пользователю редактировать содержимое ярлыка.Когда пользователь нажимает «ввод», изменения будут применены к метке, и TextInput исчезнет.

Используется как часть большой программы.И из-за того, как этот класс взаимодействует с этой программой, я не могу просто принудительно изменить текст метки на «», чтобы предотвратить исчезновение текстуры.Пустая строка "" должна быть допустимым вводом, и текстовое значение StretchingLabel должно быть равно этому значению в этих ситуациях.Но метка никогда не может иметь высоту 0, иначе пользователи не смогут взаимодействовать с ней, чтобы снова изменить значение.

код
Я пытался прослушать измененияна текстуру внутри StretchingLabel и замену height на 20, если текстуры не было.Но это не сработало.Я попытался изменить size_hint_y аналогичным образом, но произошло то же самое.

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.widget import Widget
    from kivy.uix.label import Label
    from kivy.graphics import Color
    from kivy.clock import Clock
    from kivy.uix.boxlayout import BoxLayout
    from kivy.properties import StringProperty
    from kivy.uix.textinput import TextInput
    from kivy.properties import BooleanProperty, ObjectProperty

    Builder.load_string('''
    <StretchingLabel>:
        padding: 10, 5
        size_hint_y: None
        text_size: self.width, None
        height: self.texture_size[1]
        canvas.before:
            Color:
                rgba: .7, .7, .7, 1
            Rectangle:
                pos: self.pos
                size: self.size
    <ContainerBox>:
        orientation: 'horizontal'
        Button:
            text: 'h1'
        BoxLayout:
            orientation: 'vertical'
            size: root.size
            pos: root.pos
            Label:
                text: 'Description'
                size_hint_y: None
                height: 30
                bold: True
            MyLabelFrame:
            Label:
    ''')

    class StretchingLabel(Label):
        edit = BooleanProperty(False)
        tempStr = StringProperty("")
        textinput = ObjectProperty(None, allownone=True)

        def on_touch_down(self, touch):
            if self.collide_point(*touch.pos) and touch.is_double_tap and not self.edit:
                self.edit = True
            return super(StretchingLabel, self).on_touch_down(touch)


        def on_edit(self, instance, value):
            if not value:
                if self.textinput:
                    self.remove_widget(self.textinput)
                return
            self.textinput = t = TextInput(
                text=self.text, size_hint=(None, None),
                font_size=self.font_size, font_name=self.font_name,
                pos=self.pos, size=self.size, multiline=False)
            self.bind(pos=t.setter('pos'), size=t.setter('size'))
            self.add_widget(self.textinput)
            t.bind(on_text_validate=self.on_text_validate, focus=self.on_text_focus)

        def on_text_validate(self, instance):
            #print("StretchingLabel.on_text_validate() new text:", instance.text)
            self.tempStr = instance.text
            self.edit = False

        def on_text_focus(self, instance, focus):
            if focus is False:
                #If a used defocusses the text input without hitting "enter", the changes are discarded
                #this allows the users to easily "back out" and revert their change if they accidentally messed it up
                #self.tempStr = instance.text #so this is commented out
                self.edit = False

        def on_height(self, instance, value):
            print("on_height():", self, instance, value)

        def on_size_hint_y(self, instance, value):
            print("on_size_hint_y():", self, instance, value)

        def on_texture(self, instance, value):
            #If there is no texture, I want the label to have a minimum size to stay clickable
            print("on_texture():", self, instance, value)
            if value==None:
                self.size_hint_y = 0.5
                #self.height = 20
            else:
                self.size_hint_y = None
                #self.height = self.texture_size[1]
            #after this point, the changes go through, but height goes back to 0 no matter what

    class MyLabelFrame(Widget):
        c_value = StringProperty(
            'Lorem ipsum dolor sit amet, consectetur adipiscing elit. \n\nProin vitae turpis ornare urna elementum pharetra non et tortor. Curabitur semper mattis viverra. \nPellentesque et lobortis purus, eu ultricies est. Nulla varius ac dolor quis mattis. Pellentesque vel accumsan tellus. Donec a nunc urna. Nulla convallis dignissim leo, tempor sagittis orci sollicitudin aliquet. Duis efficitur ex vel auctor ultricies. Etiam feugiat hendrerit mauris suscipit gravida. Quisque lobortis vitae ligula eget tristique. Nullam a nulla id enim finibus elementum eu sit amet elit.')

        def __init__(self, **kwargs):
            super(MyLabelFrame, self).__init__(**kwargs)
            Clock.schedule_once(lambda dt: self.makeLabel(), timeout=0.1)

        def makeLabel(self):
            c_label = StretchingLabel()
            self.bind(pos=c_label.setter('pos'), width=c_label.setter('width'), c_value=c_label.setter('text'))
            c_label.bind(tempStr=self.setValue)
            self.add_widget(c_label)
            Clock.schedule_once(lambda dt: self.chg_text(), 0.5)

        def chg_text(self):
            # this forces a property event so the label's text will be changed
            self.property('c_value').dispatch(self)

        def setValue(self, instance, val):
            print("MyLabelFrame.setValue() instance:", instance)
            self.c_value = val

    class ContainerBox(BoxLayout):
        def __init__(self, **kwargs):
            super(ContainerBox, self).__init__(**kwargs)

    class Nested2App(App):
        def build(self):
            return ContainerBox()

    if __name__ == '__main__':
        Nested2App().run()

результат
Когда я запустил этот код и использовал TextInput для изменениязначение «» (сначала я должен был изменить его на «», затем «»), высота метки изменилась на 0 и исчезла, оставив меня в журнале.

MyLabelFrame.setValue() instance: <__main__.StretchingLabel object at 0x0000000003444800>
on_texture(): <__main__.StretchingLabel object at 0x0000000003444800> <__main__.StretchingLabel object at 0x0000000003444800> None
on_height(): <__main__.StretchingLabel object at 0x0000000003444800> <__main__.StretchingLabel object at 0x0000000003444800> 20
on_height(): <__main__.StretchingLabel object at 0x0000000003444800> <__main__.StretchingLabel object at 0x0000000003444800> 0

Как вы можете видетьздесь высота действительно изменилась до 20, но в любом случае она просто изменилась на 0. Как мне предотвратить это?

...