如何调整可变高度文本属性 kivy?
Posted
技术标签:
【中文标题】如何调整可变高度文本属性 kivy?【英文标题】:How I can adjust variable height text property kivy? 【发布时间】:2013-09-11 07:35:12 【问题描述】:我有一个很长的 kivy 文本。我想调整动态高度取决于文本的数量。
我的代码是这样的。
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
class DynamicHeight(App):y
def build(self):
grid = gl = GridLayout(cols=1)
for i in range(3):
l = Label(text='Text a longer line line line line line line line line', halign='left',text_size=(300, None))
grid.add_widget(l)
return grid
DynamicHeight().run()
我要根据文字的多少调整那个label的高度或者gridlayout的行高。
【问题讨论】:
【参考方案1】:虽然已经提出了一些解决方案,但我觉得他们没有利用 kivy 的做事方式,而且这种方式更干净。您需要将 text_size 绑定到可用宽度,并将小部件的高度绑定到渲染的纹理大小。
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
class MyApp(App):
def build(self):
root = FloatLayout()
b = GridLayout(
cols=1,
pos_hint=
'center_x': .5,
'center_y': .5,
size_hint=(None, None),
spacing=20,
width=200)
b.bind(minimum_height=b.setter('height'))
root.add_widget(b)
for text_length in range(0, 80, 20):
l = Label(
text='word ' * text_length,
size_hint_y=None)
l.bind(width=lambda s, w:
s.setter('text_size')(s, (w, None)))
l.bind(texture_size=l.setter('size'))
b.add_widget(l)
return root
if __name__ == '__main__':
MyApp().run()
【讨论】:
【参考方案2】:在 thopiekar 的帮助下,我找到了解决方案。
对于那些需要它的人。到目前为止,我还没有发现没有这种方法的kivy可以做
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class MultiLineLabel(Button):
def __init__(self, **kwargs):
super(MultiLineLabel, self).__init__( **kwargs)
self.text_size = self.size
self.bind(size= self.on_size)
self.bind(text= self.on_text_changed)
self.size_hint_y = None # Not needed here
def on_size(self, widget, size):
self.text_size = size[0], None
self.texture_update()
if self.size_hint_y == None and self.size_hint_x != None:
self.height = max(self.texture_size[1], self.line_height)
elif self.size_hint_x == None and self.size_hint_y != None:
self.width = self.texture_size[0]
def on_text_changed(self, widget, text):
self.on_size(self, self.size)
class DynamicHeight(App):
def build(self):
grid = GridLayout(cols=1,size_hint_x=None, )
l=['This Text very long, should add multiple lines, automatically. This Text very long, should add multiple lines, automatically', 'One line']
for i in l:
l = MultiLineLabel(text=i)
grid.add_widget(l)
return grid
DynamicHeight().run()
而且效果很好!!!!!!
【讨论】:
新手问题.. 为什么要为这个子类按钮?标签似乎没有 size 属性。【参考方案3】:text.size()
方法不会改变标签的height
属性。如果文字过长,会与下面的内容重叠:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
class DynamicHeight(App):
def build(self):
layout = GridLayout(cols=1, spacing=20)
l = Label(text='! '*100, text_size=(10, None), size_hint_y=None, height=10)
b = Button(text='...', size_hint_y=None)
layout.add_widget(l)
layout.add_widget(b)
return layout
DynamicHeight().run()
您需要计算文本的高度并手动设置height
属性。我不知道有什么好的和干净的方法来做到这一点。这是一个肮脏的方式:
before = label._label.render()
label.text_size=(300, None)
after = label._label.render()
label.height = (after[1]/before[1])*before[1] # ammount of rows * single row height
例子:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
class DynamicHeight(App):
def build(self):
layout = GridLayout(cols=1, size_hint_y=None, spacing=20)
layout.bind(minimum_height=layout.setter('height'))
for i in xrange(1, 20):
l = Label(text='Text ' * (i*10), text_size=(300, None), size_hint_y=None)
# calculating height here
before = l._label.render()
l.text_size=(300, None)
after = l._label.render()
l.height = (after[1]/before[1])*before[1] # ammount of rows * single row height
# end
layout.add_widget(l)
root = ScrollView()
root.add_widget(layout)
return root
DynamicHeight().run()
【讨论】:
【参考方案4】:根据 tshirtman 的回答,我创建了在 kv-lang 中执行相同操作的代码。发生了什么可能会更清楚一些,因为您不需要分析回调函数。
发生的情况是标签的宽度根据布局设置,而高度设置为文本的纹理大小。所以随着文本字符串变长,纹理只能增加高度,我们可以在上面应用,通过将 boxlayout 的高度设置为 my_label.height。
# -*- coding:utf8 -*-
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.core.window import Window
Window.size = (400, 700)
PLACEHOLDER_TEXT = u'''The bindings illustrated in tshirtman's example are created automatically when using kv-lang.
Notice how the "id: my_label" allows us to access the Label's attributes in the BoxLayout's height declaration.'''
kv_string = """
<Example>:
orientation: 'vertical'
BoxLayout:
# colored background for affected area:
canvas.before:
Color:
rgba: 0.3, .4, .4, .6
Rectangle:
pos: self.pos
size: self.size
size_hint_y: None
height: my_label.height
Label:
id: my_label
text: root.text
font_size: '14dp'
text_size: (self.width, None)
size: self.texture_size
valign: 'top'
halign: 'left'
BoxLayout:
orientation: 'vertical'
size_hint_y: 1
canvas.before:
Color:
rgba: 0.9, .0, .5, .6
Rectangle:
pos: self.pos
size: self.size
TextInput:
text: root.PLACEHOLDER_TEXT
on_text: root.text = self.text
text_size: self.size
auto_indent: True
Label:
size_hint_y: None
height: '50dp'
text: 'String length: ' + str(len(root.text))
"""
Builder.load_string( kv_string )
class Example (BoxLayout ):
PLACEHOLDER_TEXT = PLACEHOLDER_TEXT
text = StringProperty( )
def __init__(self, **kwargs):
super( Example, self).__init__(**kwargs)
class MyApp(App):
def build(self):
root = Example()
return root
MyApp().run()
【讨论】:
以上是关于如何调整可变高度文本属性 kivy?的主要内容,如果未能解决你的问题,请参考以下文章
如何在列表视图中为带有自动换行的可变多行长文本自动调整项目高度?
Python Kivy 错误:“kivy.properties.ObjectProperty”对象没有属性文本