ppizarror / pygame-menu

A menu for pygame. Simple, and easy to use
https://pygame-menu.readthedocs.io/
Other
544 stars 141 forks source link

How do I limit the size of a label in px? #462

Closed Merklins closed 1 year ago

Merklins commented 1 year ago

Hi! I need to restrict the label to 291x144 px and move it to coordinates 569, 195. How to move I know using set_position, before doing render menu and then start drawing each button. I tried the set_max_width and set_max_height methods, but they did not do what I needed and it is also desirable that if the text does not fit, then scroll down appears.

Screenshot

While writing the article, I thought of using max_char, but this error comes out, am I doing something wrong? Menu version pygame_menu. 4.4.1, pygame 2.1.3.dev 8, (SDL 2.0.22, Python 3.11.1)

Screenshot2

import sys
import pygame
import pygame_menu

pygame.init()
screen = pygame.display.set_mode((1280, 720), pygame.FULLSCREEN)
clock = pygame.time.Clock()
menus = pygame_menu.Menu('Start', 1280, 720)

lab = menus.add.label(
    'Some long long long long long long long long long long long long long text',
    max_char=10
)

surface = pygame.Surface((450, 339), pygame.SRCALPHA)
pygame.draw.rect(surface, (0, 0, 0), (0, 0, 450, 339), width=5, border_top_left_radius=50)
pygame.draw.rect(surface, (0, 0, 0), (149, 0, 301, 154), width=5)

menus.render()

while True:
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    key = pygame.key.get_pressed()

    if key[pygame.K_ESCAPE]:
        pygame.quit()
        sys.exit()

    screen.fill((0, 255, 0))
    screen.blit(surface, (415, 190))

    lab.set_position(569, 195)
    lab.draw(screen)
    lab.update(events)

    pygame.display.update()
ppizarror commented 1 year ago

Hi, the problem relies on max_char itself because it generates a list of widgets rather than a single widget. To use lab you must iterate it as a list. I've updated your example, it is not the best solution, but at least solves your issue:

import sys
import pygame
import pygame_menu

pygame.init()
screen = pygame.display.set_mode((1280, 720), pygame.FULLSCREEN)
clock = pygame.time.Clock()
menus = pygame_menu.Menu('Start', 1280, 720)

lab = menus.add.label(
    'Some long long long long long long long long long long long long long text',
    font_size=12,
    max_char=10,
)

surface = pygame.Surface((450, 339), pygame.SRCALPHA)
pygame.draw.rect(surface, (0, 0, 0), (0, 0, 450, 339), width=5, border_top_left_radius=50)
pygame.draw.rect(surface, (0, 0, 0), (149, 0, 301, 154), width=5)

menus.render()

while True:
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    key = pygame.key.get_pressed()

    if key[pygame.K_ESCAPE]:
        pygame.quit()
        sys.exit()

    screen.fill((0, 255, 0))
    screen.blit(surface, (415, 190))

    for i in range(len(lab)):
        lab[i].set_position(575, 185 + lab[i].get_height(apply_padding=False) * (i + 1))
        lab[i].draw(screen)
        lab[i].update(events)

    pygame.display.update()
ppizarror commented 1 year ago

Also, you can use wordwrap=True to get the same result without having to split it in different widgets, see docs:

:param wordwrap: Wraps label if newline is found on widget. If False the manager splits the string and creates a list of widgets, else, the widget itself splits and updates the height

Example:

import sys
import pygame
import pygame_menu

pygame.init()
screen = pygame.display.set_mode((1280, 720), pygame.FULLSCREEN)
clock = pygame.time.Clock()
menus = pygame_menu.Menu('Start', 1280, 720)

lab = menus.add.label(
    'Some long long long\nlong long long long long long\nlong long long long text',
    font_size=12,
    wordwrap=True
)

surface = pygame.Surface((450, 339), pygame.SRCALPHA)
pygame.draw.rect(surface, (0, 0, 0), (0, 0, 450, 339), width=5, border_top_left_radius=50)
pygame.draw.rect(surface, (0, 0, 0), (149, 0, 301, 154), width=5)

menus.render()

while True:
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    key = pygame.key.get_pressed()

    if key[pygame.K_ESCAPE]:
        pygame.quit()
        sys.exit()

    screen.fill((0, 255, 0))
    screen.blit(surface, (415, 190))

    lab.set_position(575, 195)
    lab.draw(screen)
    lab.update(events)

    pygame.display.update()
ppizarror commented 1 year ago

Also, there is another post where I showed some hacks to "limit" the size of objects, see https://github.com/ppizarror/pygame-menu/issues/461#issuecomment-1493219610.

ppizarror commented 1 year ago

Hi, I'll close this issue as completed. Greetings 😃.