1

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

alant
  • 173
  • 2
  • 13
  • if you use the same font and size that should work ... kivy by default will try to scale the text to fit its widget iirc – Joran Beasley Dec 28 '21 at 23:33
  • 1
    You can use [kivy core Label](https://kivy.org/doc/stable/api-kivy.core.text.html#module-kivy.core.text) to create a Label with whatever font, etc. Then get the size of the resulting `Texture`. – John Anderson Dec 29 '21 at 00:36
  • I tried the kivy core label but could not get it to work, I will update my question to show more. – alant Dec 29 '21 at 04:54

2 Answers2

2

Does this work :

AdaptiveLabel = Label(
    size_hint_x = None,
    text = "Custom text",
    font_size = custom_size,
    )
AdaptiveLabel.texture_update()
AdaptiveLabel.width = AdaptiveLabel.texture_size[0]
# And then,
print(AdaptiveLabel.size)

ApuCoder
  • 2,795
  • 2
  • 3
  • 19
1

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.

alant
  • 173
  • 2
  • 13