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()
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()
text = "whatever"
size_x = len(text)* 0.01
label = Label(text = text, size_hint = (size_x, None)
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()
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()
text = "whatever"
size_x = len(text)* 0.01
label = Label(text = text, size_hint = (size_x, None)