проблема
У меня есть ярлык, высота которого привязана к высоте текстуры внутри него.К сожалению, если в метке нет текста, текстуры нет, а высота установлена равной 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. Как мне предотвратить это?