Change the label size depending on the text

Question:

I want to add text to the label during the app runtime. It is placed in a FloatLayout, which is placed in a ScrollView so that I could scroll through the text. I want the FloatLayout to be size hinted as 1,1 by default, and on addition of the text, to increase its height. Should I even use size hinting or will the regular coordinate system suffice? In any case, I couldn’t get it to work. When I did a little bit of testing, I’ve found out that the text_size property of the label does not change upon addition of new text, but changes on window resize. It is probably because I’ve set the text_size property in a kv file to be equal to the size of the label to get the proper text alignment (top-left corner). Here is my code:

from kivy import require
require("1.9.1")

import string

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.effects.scroll import ScrollEffect
from kivy.uix.screenmanager import Screen, ScreenManager, NoTransition
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.floatlayout import FloatLayout

nick = ''

class MyScrollView(ScrollView):
    pass

class TextLabel(Label):
    pass

Builder.load_string('''
<MyScrollView>:
    #...canvas instructions

<TextLabel>:
    text_size: self.size
''')

class Chat(Screen):
    pass        

class ChatApp(App):
    def build(self):
        def switch_view(*args, **kwargs):
            global nick
            nick = tx1_intro.text
            lb1_main.text = "Chat with " + nick
            Screens.current = 'main'
            Window.size = (600, 500)

        def msg_in(*args, **kwargs):
            global nick
            msg = tx1_main.text.strip("n ")
            if msg not in string.whitespace:
                lb2_main.text += "{}: {}n".format(nick, msg)
            tx1_main.text = ""
            fl_layout1_main.size_hint_y += 1

        Screens = ScreenManager(transition = NoTransition())

        chat = Chat(name = "main")

        tx1_main = TextInput(size_hint = (0.9, 0.155),
                             pos_hint = {"top":0.177,"center_x":0.465}) 

        scr_view_main = MyScrollView(pos_hint = {"top":0.87, "center_x":0.5},
                                   size_hint = (0.97, 0.65),
                                   do_scroll_x = False)

        fl_layout1_main = FloatLayout(size_hint_y = 1)

        lb2_main = TextLabel(size_hint = (0.99, 0.99),
                             pos_hint = {"center_x":0.5, "center_y":0.5},
                             valign = "top",
                             color = (0, 0, 0, 1))                  

        chat.add_widget(scr_view_main)
        scr_view_main.add_widget(fl_layout1_main)
        fl_layout1_main.add_widget(lb2_main)

        Screens.add_widget(chat)

        return Screens

if __name__ == "__main__":
    ChatApp().run()
Asked By: illright

||

Answers:

Personally, I don’t like FloatLayout, but using docs is the way to find out what you need to type and what is automatic. I think BoxLayout is more practical and better for fast typing(just playing with size_hint) than FloatLayout and if you don’t work on something where you really need this type of positioning, then it’s not necessary.

First example is just simple label with scrolling, basically all in kv, so it’s good to save it and copy&paste it when you need it(or learn how to do it). The second one is the scrollable label with some widgets around just like the code you provided and only thing you need is just implement it into your code. text_size is important, but you forgot one thing – height. When you pass self.size you pass the size from the beginning, not the texture_size, what is the thing you need. Since size_hint_y is None, you can set height manually with the texture_size which is self-updating after you pass some text.

Simple scrollable label:

from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.uix.scrollview import ScrollView
Builder.load_string('''
<ScrollLabel>:
    Label:
        size_hint_y:None
        text_size:self.width,None
        text:'l or emi psum '*1000
        height:self.texture_size[1]
''')
class ScrollLabel(ScrollView):pass
runTouchApp(ScrollLabel())

Something around it:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
Builder.load_string('''
<Box>:
    orientation: 'vertical'
    FloatLayout:
        ScrollView:
            Label:
                id: lab
                size_hint_y: None
                text_size: self.width, None
                text: 'l or emi psum '*100
                height:self.texture_size[1]
    Button:
        size_hint_y: None
        height: 100
        on_release: root.ids.lab.text+='lo rem '*100
''')
class Box(BoxLayout): pass
class My(App):
    def build(self):
        return Box()
My().run()
Answered By: Peter Badida
text = "whatever"
size_x = len(text)* 0.01
label = Label(text = text, size_hint = (size_x, None)
Answered By: Przemysław Wnuk
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.