Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@wkta
Last active March 11, 2022 10:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wkta/ad44c2b2be079e906aad661c1f41a880 to your computer and use it in GitHub Desktop.
Save wkta/ad44c2b2be079e906aad661c1f41a880 to your computer and use it in GitHub Desktop.
example to show how one can manage text blocks (->GUI building) in a convenient way
"""
how can we manage text blocks (->GUI building) in a convenient way?
This may be an answer. Contributors: .wkta-tom#7412 | S_P_Y#1331
"""
import pygame
def create_txtblock_surf(text, ft_obj, color=(0, 0, 0), bg_color=(255, 255, 255), alignment_f=0.0, debug=0):
"""
goal = to produce a pygame surface
append a pair (lbl, textRect) to render_list,one per line
"""
render_list = list()
mw = mh = -1
toth = 0
for line in text.split('\n'):
text_lbl = ft_obj.render(line, True, color)
w, h = text_lbl.get_size()
if w > mw:
mw = w
if h > mh:
mh = h
toth += h
render_list.append(text_lbl)
# create surf, that represents txtblock
surf = pygame.Surface((mw, toth))
surf.fill(bg_color)
# stack labels, to gen the txt block
target_y = 0
for lbl in render_list:
curr_w = lbl.get_width()
surf.blit(lbl, (alignment_f * (mw - curr_w), target_y))
target_y += mh
if debug:
pygame.draw.rect(surf, 'red', ((0, 0), (mw - 1, toth - 1)), 1)
return surf
class TextBlock(pygame.sprite.Sprite):
ALIGN_LEFT, ALIGN_CENTER = 0, 1
def __init__(self, ft_name, ft_size, text='', color=(0, 0, 0), bg_color=(255, 255, 255)):
super().__init__()
self.ft_obj = pygame.font.Font(ft_name, ft_size)
self._color = color
self._bg_color = bg_color
self._align = self.ALIGN_CENTER
self._debug = 0
self.rect = None # no position for now
if '' == text:
self._text = ''
self.image = None
else:
self._text = text
self._refresh_img()
def _refresh_img(self):
if self.rect: # has a position
prev_pos = self.rect.center
else:
prev_pos = None
if self._align == self.ALIGN_CENTER:
ts = create_txtblock_surf(self._text, self.ft_obj, self._color, self._bg_color, 0.5, self.debug)
else:
ts = create_txtblock_surf(self._text, self.ft_obj, self._color, self._bg_color, 0.0, self.debug)
self.image = ts
self.rect = self.image.get_rect()
# restore previous position
if prev_pos:
self.rect.center = prev_pos
@property
def debug(self):
return self._debug
@debug.setter
def debug(self, v):
self._debug = 1 if v else 0
self._refresh_img()
@property
def text_align(self):
return self._align
@text_align.setter
def text_align(self, v):
if v in (self.ALIGN_LEFT, self.ALIGN_CENTER):
self._align = v
self._refresh_img()
else:
raise ValueError
@property
def text(self):
return self._text
@text.setter
def text(self, val):
self._text = val
self._refresh_img()
def draw(self, scr):
if self.image:
pos = self.rect.topleft
scr.blit(self.image, pos)
# - program body v -
pygame.init()
screen = pygame.display.set_mode((640, 480))
width, height = screen.get_size()
INIT_TXT = 'hello user this\nis\nsome\ndope\ntext'
ALT_TXT = 'i\nunderstand that\nyou watch the console'
block = TextBlock('pixel_font2.ttf', 32, INIT_TXT, (0, 0, 0))
block.rect.center = (width // 2, height // 2) # lets center the text block
# - debug if needed, comment this line when you're done debugging
block.debug = 1
print('*~*~*\npress and hold the space bar ; press ENTER to change alignment')
ended = False
while not ended:
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
ended = True
elif ev.type == pygame.KEYDOWN:
if ev.key == pygame.K_RETURN:
block.text_align = (block.text_align + 1) % 2 # switch text align
elif ev.key == pygame.K_SPACE:
block.text = ALT_TXT
elif ev.type == pygame.KEYUP:
if not pygame.key.get_pressed()[pygame.K_SPACE]:
block.text = INIT_TXT
screen.fill('white')
block.draw(screen)
pygame.display.update()
pygame.quit()
# - program body ^ -
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment