Как узнать максимальный размер шрифта текста который может поместиться в прямоугольник (Pygame)?

Я хочу сделать кнопку на pygame. Мне известны её ширина и длина, а также количество символов в тексте. Кнопка состоит из прямоугольника и текста в нём. Форматирование текста: идеально посередине %. Для этого мне нужно определить: какой максимальный размер шрифта может поместиться в прямоугольнике.

% = одно и то же значение для промежутка между верхом поверхности текста и верхом кнопки (аналогично с низом), для промежутка между левым краем поверхности текста и левым краем кнопки (аналогично с правым). Эти промежутки не обязательно равны.

class button:
    def init(self, width, height, text):
        self.rect = pygame.Rect(0, 0, width, height)
        self.text_surface = pygame.font.SysFont('consolas', ТУТ РАЗМЕР ШРИФТА).render(text, False, (0, 0, 0))
    
    def draw(self):
        pg.draw.rect(win, (255, 255, 255), self.rect)
        
        ## Второй аргумент функции blit отвечает за "идеально посередине"
        win.blit(self.text_surface, ((self.rect[2] - self.text_surface.get_rect()[2]) // 2, (self.rect[3] - self.text_surface.get_rect()[3]) // 2)

Если всё ещё не понятно (что скорее всего правда), то, коротко, проблема в том что я хочу отрисовать текст посередине и в границах кнопки а если сделать его слишком большим или слишком маленьким, то текст будет выходить за рамки


Ответы (1 шт):

Автор решения: Igen

Возможно, код слишком громоздкий, но он рабочий. Размер учитывается и по вертикали и по горизонтали.

def get_diff(font_name,standart_size,ind=0):
    '''
    Функция получает разницу в пикселях, достаточной для изменения размера шрифта на 1 пункт в нужном измерении
    ind=0 - по оси x
    ind=1 - по оси y
    '''
    x=pygame.font.SysFont(font_name, standart_size).render(".", False, (0, 0, 0)).get_size()[ind]
    y=x
    newSize,i=0,0
    while y==x:
        newSize=standart_size+i
        y=pygame.font.SysFont(font_name, newSize).render(".", False, (0, 0, 0)).get_size()[ind]
        i+=1
    return newSize-standart_size

class button:
    def __init__(self, width, height, text,font_name="consolas",stpos=[0,0]):
        self.rect = pygame.Rect(0, 0, width, height)
        self.stpos=stpos
        
        # Получение стандартных размеров для буквы, конкретного шрифта
        width_simb,height_simb=pygame.font.SysFont(font_name, 10).render(".", False, (0, 0, 0)).get_size()
        diff_x,diff_y=get_diff(font_name,10),get_diff(font_name,10,ind=1)
        #Максимальное увеличение надписи для упаковки
        size=(width//diff_x)
        
        self.text_surface = pygame.font.SysFont(font_name, size).render(text, False, (255,255,255))
        surf_size=self.text_surface.get_size()
        
        #"Упаковка" надписи в вертикальные границы
        if self.text_surface.get_height()>height:
            while surf_size[1]>height:
                self.text_surface = pygame.font.SysFont(font_name, size).render(text, False, (255,255,255))
                surf_size=self.text_surface.get_size()
                size-=1
        #"Упаковка" надписи в горизонтальные границы
        if self.text_surface.get_width()>width:
            while surf_size[0]>width:
                self.text_surface = pygame.font.SysFont(font_name, size).render(text, False, (255,255,255))
                surf_size=self.text_surface.get_size()
                size-=1
        '''
        После упаковки может остаться 2 пикселя до границы кнопки
        Примечание: для шрифта "consolas" упаковка не требуется
        '''
    def draw(self):
        '''
        Добавлен параметр self.stpos для стартовой позиции
        '''
        pygame.draw.rect(win, (0, 0, 255), [self.stpos[0],self.stpos[1],self.rect.width,self.rect.height])
        win.blit(self.text_surface, (self.stpos[0]+(self.rect[2] - self.text_surface.get_rect()[2]) // 2, self.stpos[1]+(self.rect[3] - self.text_surface.get_rect()[3]) // 2))

→ Ссылка