2013-09-07 2 views
4

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

Я хочу, чтобы высота метки или высота строки регулировки сетки в зависимости от количества текста.

ответ

0

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

Вам нужно вычислить Heigh текста и установить его с 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() 
0

Я нашел решение, с помощью 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, width="300dp") 

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

И работает отлично !!!!!

4

Несмотря на то, что уже есть решения, я чувствую, что они не используют способ обитания киви, и что этот способ чище. Вам нужно привязать 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_lenght in range(0, 80, 20): 
      l = Label(
       text='word ' * text_lenght, 
       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() 
0

Вслед за ответом tshirtman, я создал код для делать то же самое в кв-лана. Это может быть немного яснее, что происходит, поскольку вам не нужно анализировать функции обратного вызова.

Что происходит, так это то, что ширина метки устанавливается в соответствии с макетом, а высота устанавливается на размер текстуры текста. Так как текстовая строка становится длиннее, текстура может расти только по высоте, которую мы можем применить выше, установив высоту 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()