Search code examples
pythonkivykivy-languagekivymd

How to set kivy font size inside a label or a button so it fill the label or the button even the label or the button size changes


I am trying to build an application with buttons (similar to the calculator), everything was good until I tries to make the app window thinner, the text go out the borders of the button. I tried font_size: self.width/5 to change the font with the screen size but it works in one situation (width or height) I also found a code

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.label import Label


class MyLabel(Image):
    text = StringProperty('')

    def on_text(self, *_):
        # Just get large texture:
        l = Label(text=self.text)
        l.font_size = '1000dp'  # something that'll give texture bigger than phone's screen size
        l.texture_update()
        # Set it to image, it'll be scaled to image size automatically:
        self.texture = l.texture


class RootWidget(BoxLayout):
    pass


class TestApp(App):
    def build(self):
        return MyLabel(text='Test test test')


if __name__ == '__main__':
    TestApp().run()

that solved this problem but it was using Image in kivy and I don't know how to use it in my situation or in the kv file.

Currently texts are like this:
Problem image

THANKS!


Solution

  • You can use kivy.core.text.Label to calculate sizes of rendered text, and adjust the font size to make the text fit the Label. Here is a custom Label class that does it:

    from kivy.core.text import Label as CoreLabel
    from kivy.core.text.markup import MarkupLabel
    
    def MyLabel(Label):
        # this Label automatically adjusts font size to fill the Label
        def on_text(self, instance, new_text):
            self.adjust_font_size()
    
        def on_size(self, instance, new_size):
            self.adjust_font_size()
    
        def adjust_font_size(self):
            font_size = self.font_size
            while True:
                # this loops reduces font size if needed
                if self.markup:
                    cl = MarkupLabel(font_name=self.font_name, font_size=font_size, text=self.text)
                else:
                    cl = CoreLabel(font_name=self.font_name, font_size=font_size, text=self.text)
                cl.refresh()
                if font_size > self.height - self.padding_y * 2:
                    font_size = self.height - self.padding_y * 2
                elif cl.content_width > self.width - self.padding_x * 2 or \
                        cl.content_height > self.height - self.padding_y * 2:
                    font_size *= 0.95
                else:
                    break
            while True:
                # this loop increases font size if needed
                if self.markup:
                    cl = MarkupLabel(font_name=self.font_name, font_size=font_size, text=self.text)
                else:
                    cl = CoreLabel(font_name=self.font_name, font_size=font_size, text=self.text)
                cl.refresh()
                if cl.content_width * 1.1 < self.width - self.padding_x * 2 and \
                        cl.content_height * 1.1 < self.height - self.padding_y * 2:
                    font_size *= 1.05
                else:
                    break
    
            self.font_size = font_size