ScalaBoy
ScalaBoy

Reputation: 3392

How to add a text inside rectangle?

I defined the class of the objects fences as follows:

class GeoFence(pygame.sprite.Sprite):
    def __init__(self, rect, risk_level, *groups):
        self._layer = 1
        pygame.sprite.Sprite.__init__(self, groups)
        self.image = pygame.surface.Surface((rect.width, rect.height))
        self.image.fill(GREEN)
        self.rect = rect
        self.risk_level = risk_level
        self.font = pygame.font.SysFont('Arial', 25)
        screen.blit(self.font.render(risk_level, True, (255,0,0)), (200, 100))

Each object fence is a green rectangle. I want to display a text inside this rectangle. The text is defined by a string risk_level that is selected randomly from the list risks.

all_sprites = pygame.sprite.LayeredUpdates()
fences = pygame.sprite.Group()

risks = ["HIGH","MEDIUM","LOW"]
for rect in (pygame.Rect(510,150,75,52), pygame.Rect(450,250,68,40), pygame.Rect(450,370,68,48)):
    risk = risks[random.randint(0,2)]
    GeoFence(rect, risk, all_sprites, fences)

This code does not fail, but the titles are not displayed anywhere on the screen.

Upvotes: 1

Views: 984

Answers (1)

skrx
skrx

Reputation: 20468

The problem is that you're blitting the text at the coordinates (200, 100) of the screen surface when the sprites are created, so the text will disappear when the screen gets cleared in the next frame.

In order to blit the text on the GeoFence objects, you need to blit it onto the self.image at the coordinates (0, 0) (if it should be top left aligned).

If the surface should fit to the size of the text, you can render the text surface first and use its size as the size of the self.image surface.

import random
import pygame


pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
BG_COLOR = pygame.Color('gray12')
GREEN = pygame.Color('green')
FONT = pygame.font.SysFont('Arial', 25)


class GeoFence(pygame.sprite.Sprite):

    def __init__(self, rect, risk_level, *groups):
        self._layer = 1
        pygame.sprite.Sprite.__init__(self, groups)
        text_surface = FONT.render(risk_level, True, (255,0,0))
        self.image = pygame.surface.Surface(text_surface.get_size())
        self.image.fill(GREEN)
        self.image.blit(text_surface, (0, 0))
        self.rect = self.image.get_rect(topleft=rect.topleft)
        self.risk_level = risk_level


all_sprites = pygame.sprite.LayeredUpdates()
fences = pygame.sprite.Group()

risks = ["HIGH","MEDIUM","LOW"]
for rect in (pygame.Rect(510,150,75,52), pygame.Rect(450,250,68,40),
             pygame.Rect(450,370,68,48)):
    risk = random.choice(risks)
    GeoFence(rect, risk, all_sprites, fences)

done = False
while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    all_sprites.update()

    screen.fill(BG_COLOR)
    all_sprites.draw(screen)
    pygame.display.flip()
    clock.tick(60)

It's also possible to pass another color to Font.render which will be used as the background color. That would allow you to shorten the code a little bit:

class GeoFence(pygame.sprite.Sprite):

    def __init__(self, rect, risk_level, *groups):
        self._layer = 1
        pygame.sprite.Sprite.__init__(self, groups)
        self.image = FONT.render(risk_level, True, (255,0,0), GREEN)
        self.rect = self.image.get_rect(topleft=rect.topleft)
        self.risk_level = risk_level

If you want to center the text, create another rect for the text, set its center coords to the self.rect.center and then use it as the blit position for the text. The self.rect should still be at the default position (0, 0) when you do this.

def __init__(self, rect, risk_level, *groups):
    self._layer = 1
    pygame.sprite.Sprite.__init__(self, groups)
    text_surface = FONT.render(risk_level, True, (255,0,0))
    self.image = pygame.surface.Surface(
        (text_surface.get_width()+110, text_surface.get_height()+20))
    self.image.fill(GREEN)
    # Create the rect, but don't set the coordinates yet.
    self.rect = self.image.get_rect()
    # Set the center of the text_rect to the center of the self.rect.
    text_rect = text_surface.get_rect(center=self.rect.center)
    # Then blit the text at the text_rect and it will be centered.
    self.image.blit(text_surface, text_rect)
    # Afterwards set the rect to the desired position.
    self.rect.topleft = rect.topleft

Upvotes: 1

Related Questions