pythonkivykivy-languagekivymd

How to calculate the length of a string in pixels for specific font and size, using KIVY API?


I would like to find the length of a string in pixels using KIVY, for the default or a specified font and size.

I found a similar question, How to calculate length of string in pixels for specific font and size? with a solution using PIL, which I could not make work:

from PIL import ImageFont
font = ImageFont.truetype('times.ttf', 12)
size = font.getsize('Hello world')
print(size)

How can I make the snippet above or something similar work using the cross-platform KIVY API?

I looked in the kivy metrics (https://kivy.org/doc/stable/api-kivy.metrics.html) and core.text docs (https://kivy.org/doc/stable/api-kivy.core.text.html), which have relevant methods, but I could not find what I needed.

based on the comment below from @johnAnderson, I tried the following, but I am getting a segmentation fault:

from kivy.core.text import Label as CoreLabel

my_label = CoreLabel()
my_label.text = 'hello'
my_label.refresh()
hello_texture = my_label.texture
print(hello_texture.text_size())

Any pointers would be appreciated. Thanks


Solution

  • Thanks all. @JohnAnderson and @ApuCoder, set me on the right path. Going through the kivy.core.text documentations, I found the following way of doing what I was after:

    from kivy.core.text import Label as CoreLabel
    string = 'Hello world'
    my_label = CoreLabel(
        font_size=12,
    )
    print(f'{my_label.get_extents(string)=}')
    

    The above (using the get_extents(str) method) returns the same results as the method suggested by @ApuCoder, but it doesn't require the instantiation of a kivy label. The method suggested by @ApuCoder (with small modifications) is:

    from kivy.uix.label import Label
    string = 'Hello world'
    AdaptiveLabel = Label(
        text=string,
        font_size=12,
        )
    AdaptiveLabel.texture_update()
    AdaptiveLabel.width = AdaptiveLabel.texture_size[0]
    print(f'{AdaptiveLabel.texture_size=}')
    

    both return:

    my_label.get_extents(string)=(61, 15)
    AdaptiveLabel.texture_size=[61, 15]
    

    Note, if I don't initialize the font_size, the default for CoreLabel is 12, but for kivy.uix.Label is 15.

    The final snippet:

    import kivy.core.text
    def get_str_pixel_width(string: str, **kwargs) -> int:
        return kivy.core.text.Label(**kwargs).get_extents(string)[0]
    

    Thank you all, I hope this helps.