How to Create a Text Input Box With Pygame

How can I create a text input box with Pygame?

You can define a rect as the area of the input box. If a pygame.MOUSEBUTTONDOWN event occurs, use the colliderect method of the input_box rect to check if it collides with the event.pos and then activate it by setting a active variable to True.

If the box is active you can type something and Pygame will generate pygame.KEYDOWN events which have a unicode attribute that you can simply add to a string, e.g. text += event.unicode. If the user presses enter, you can do something with the text string (in the example I just print it) and reset it to ''.

import pygame as pg


def main():
screen = pg.display.set_mode((640, 480))
font = pg.font.Font(None, 32)
clock = pg.time.Clock()
input_box = pg.Rect(100, 100, 140, 32)
color_inactive = pg.Color('lightskyblue3')
color_active = pg.Color('dodgerblue2')
color = color_inactive
active = False
text = ''
done = False

while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
if event.type == pg.MOUSEBUTTONDOWN:
# If the user clicked on the input_box rect.
if input_box.collidepoint(event.pos):
# Toggle the active variable.
active = not active
else:
active = False
# Change the current color of the input box.
color = color_active if active else color_inactive
if event.type == pg.KEYDOWN:
if active:
if event.key == pg.K_RETURN:
print(text)
text = ''
elif event.key == pg.K_BACKSPACE:
text = text[:-1]
else:
text += event.unicode

screen.fill((30, 30, 30))
# Render the current text.
txt_surface = font.render(text, True, color)
# Resize the box if the text is too long.
width = max(200, txt_surface.get_width()+10)
input_box.w = width
# Blit the text.
screen.blit(txt_surface, (input_box.x+5, input_box.y+5))
# Blit the input_box rect.
pg.draw.rect(screen, color, input_box, 2)

pg.display.flip()
clock.tick(30)


if __name__ == '__main__':
pg.init()
main()
pg.quit()

Here's an object-oriented variant that allows you to easily create multiple input boxes:

import pygame as pg


pg.init()
screen = pg.display.set_mode((640, 480))
COLOR_INACTIVE = pg.Color('lightskyblue3')
COLOR_ACTIVE = pg.Color('dodgerblue2')
FONT = pg.font.Font(None, 32)


class InputBox:

def __init__(self, x, y, w, h, text=''):
self.rect = pg.Rect(x, y, w, h)
self.color = COLOR_INACTIVE
self.text = text
self.txt_surface = FONT.render(text, True, self.color)
self.active = False

def handle_event(self, event):
if event.type == pg.MOUSEBUTTONDOWN:
# If the user clicked on the input_box rect.
if self.rect.collidepoint(event.pos):
# Toggle the active variable.
self.active = not self.active
else:
self.active = False
# Change the current color of the input box.
self.color = COLOR_ACTIVE if self.active else COLOR_INACTIVE
if event.type == pg.KEYDOWN:
if self.active:
if event.key == pg.K_RETURN:
print(self.text)
self.text = ''
elif event.key == pg.K_BACKSPACE:
self.text = self.text[:-1]
else:
self.text += event.unicode
# Re-render the text.
self.txt_surface = FONT.render(self.text, True, self.color)

def update(self):
# Resize the box if the text is too long.
width = max(200, self.txt_surface.get_width()+10)
self.rect.w = width

def draw(self, screen):
# Blit the text.
screen.blit(self.txt_surface, (self.rect.x+5, self.rect.y+5))
# Blit the rect.
pg.draw.rect(screen, self.color, self.rect, 2)



def main():
clock = pg.time.Clock()
input_box1 = InputBox(100, 100, 140, 32)
input_box2 = InputBox(100, 300, 140, 32)
input_boxes = [input_box1, input_box2]
done = False

while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
for box in input_boxes:
box.handle_event(event)

for box in input_boxes:
box.update()

screen.fill((30, 30, 30))
for box in input_boxes:
box.draw(screen)

pg.display.flip()
clock.tick(30)


if __name__ == '__main__':
main()
pg.quit()

There are also third party modules available like pygame_textinput.

Add text into a colored input text box pygame

The result I am getting is that the text is behind the input

So, you have to draw the background before the text:

class InputBox:
# [...]

def draw(self, screen):
# Draw the background of the text box
pygame.draw.rect(screen, (255, 255, 255), self.inner_rect)
# Blit the text.
screen.blit(self.txt_surface, (self.rect.x+5, self.rect.y+5))
# Blit the rect.
pygame.draw.rect(screen, self.color, self.rect, 2)

Sample Image

How to get text input from user in Pygame?

Here is an example script that blits input to the screen. It shows how you can modify a name string while looping through the pygame event queue. Each frame, the screen is cleared and the name surface is rebuilt and blit.

import pygame
from pygame.locals import *

def name():
pygame.init()
screen = pygame.display.set_mode((480, 360))
name = ""
font = pygame.font.Font(None, 50)
while True:
for evt in pygame.event.get():
if evt.type == KEYDOWN:
if evt.unicode.isalpha():
name += evt.unicode
elif evt.key == K_BACKSPACE:
name = name[:-1]
elif evt.key == K_RETURN:
name = ""
elif evt.type == QUIT:
return
screen.fill((0, 0, 0))
block = font.render(name, True, (255, 255, 255))
rect = block.get_rect()
rect.center = screen.get_rect().center
screen.blit(block, rect)
pygame.display.flip()

if __name__ == "__main__":
name()
pygame.quit()

Here is a gist version

displaying text box in pygame

I found this online
https://www.codegrepper.com/code-examples/python/how+to+make+a+text+input+box+python+pygame

import pygame as pg


pg.init()
screen = pg.display.set_mode((640, 480))
COLOR_INACTIVE = pg.Color('lightskyblue3')
COLOR_ACTIVE = pg.Color('dodgerblue2')
FONT = pg.font.Font(None, 32)


class InputBox:

def __init__(self, x, y, w, h, text=''):
self.rect = pg.Rect(x, y, w, h)
self.color = COLOR_INACTIVE
self.text = text
self.txt_surface = FONT.render(text, True, self.color)
self.active = False

def handle_event(self, event):
if event.type == pg.MOUSEBUTTONDOWN:
# If the user clicked on the input_box rect.
if self.rect.collidepoint(event.pos):
# Toggle the active variable.
self.active = not self.active
else:
self.active = False
# Change the current color of the input box.
self.color = COLOR_ACTIVE if self.active else COLOR_INACTIVE
if event.type == pg.KEYDOWN:
if self.active:
if event.key == pg.K_RETURN:
print(self.text)
self.text = ''
elif event.key == pg.K_BACKSPACE:
self.text = self.text[:-1]
else:
self.text += event.unicode
# Re-render the text.
self.txt_surface = FONT.render(self.text, True, self.color)

def update(self):
# Resize the box if the text is too long.
width = max(200, self.txt_surface.get_width()+10)
self.rect.w = width

def draw(self, screen):
# Blit the text.
screen.blit(self.txt_surface, (self.rect.x+5, self.rect.y+5))
# Blit the rect.
pg.draw.rect(screen, self.color, self.rect, 2)



def main():
clock = pg.time.Clock()
input_box1 = InputBox(100, 100, 140, 32)
input_box2 = InputBox(100, 300, 140, 32)
input_boxes = [input_box1, input_box2]
done = False

while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
for box in input_boxes:
box.handle_event(event)

for box in input_boxes:
box.update()

screen.fill((30, 30, 30))
for box in input_boxes:
box.draw(screen)

pg.display.flip()
clock.tick(30)


if __name__ == '__main__':
main()
pg.quit()

I hope it helps!

Using text inputs in pygame

I've tryed using Tk but the thing about using is it stops the whole pygame program when the Tk window pops up and its just not good

this is what i use Pygame InputBox its not the prettiest but it works great just download it and its really easy to use

just import inputbox

then do something like this:

inp = int(inputbox.ask(screen, 'Message')) #inp will equal whatever the input is

this is pretty much like raw_input but for pygame

its not the most aesthetically pleasing but im sure if you search around you can find maybe a nicer one

Paragraph input in pygame

You must combine the answers to the following questions:

  • How to create a text input box with pygame?
  • Rendering text with multiple lines in pygame

Use the code for the text input box form How to create a text input box with pygame? and render the texture using the drawText function from Rendering text with multiple lines in pygame.

Minimal example based on the code from the question:

Sample Image

import pygame 

pygame.init()
screen = pygame.display.set_mode((600,600))
app_fps = pygame.time.Clock()
font = pygame.font.SysFont(None,32)
active_color = pygame.Color('dodgerblue2')
inactive_color = pygame.Color('white')

textAlignLeft = 0
textAlignRight = 1
textAlignCenter = 2
textAlignBlock = 3

def drawText(surface, text, color, rect, font, align=textAlignLeft, aa=False, bkg=None):
lineSpacing = -2
spaceWidth, fontHeight = font.size(" ")[0], font.size("Tg")[1]

listOfWords = text.split(" ")
if bkg:
imageList = [font.render(word, 1, color, bkg) for word in listOfWords]
for image in imageList: image.set_colorkey(bkg)
else:
imageList = [font.render(word, aa, color) for word in listOfWords]

maxLen = rect[2]
lineLenList = [0]
lineList = [[]]
for image in imageList:
width = image.get_width()
lineLen = lineLenList[-1] + len(lineList[-1]) * spaceWidth + width
if len(lineList[-1]) == 0 or lineLen <= maxLen:
lineLenList[-1] += width
lineList[-1].append(image)
else:
lineLenList.append(width)
lineList.append([image])

lineBottom = rect[1]
lastLine = 0
for lineLen, lineImages in zip(lineLenList, lineList):
lineLeft = rect[0]
if align == textAlignRight:
lineLeft += + rect[2] - lineLen - spaceWidth * (len(lineImages)-1)
elif align == textAlignCenter:
lineLeft += (rect[2] - lineLen - spaceWidth * (len(lineImages)-1)) // 2
elif align == textAlignBlock and len(lineImages) > 1:
spaceWidth = (rect[2] - lineLen) // (len(lineImages)-1)
if lineBottom + fontHeight > rect[1] + rect[3]:
break
lastLine += 1
for i, image in enumerate(lineImages):
x, y = lineLeft + i*spaceWidth, lineBottom
surface.blit(image, (round(x), y))
lineLeft += image.get_width()
lineBottom += fontHeight + lineSpacing

if lastLine < len(lineList):
drawWords = sum([len(lineList[i]) for i in range(lastLine)])
remainingText = ""
for text in listOfWords[drawWords:]: remainingText += text + " "
return remainingText
return ""

class InputBox():
def __init__(self,max_len,x,y,width,height,text = ''):
self.color = inactive_color
self.len = max_len
self.rect = pygame.Rect(x,y,width,height)
self.text = text
self.text_surf = font.render(text,True,self.color)
self.active = False

def event_handler(self,event):
if event.type == pygame.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
self.active = not self.active
else:
self.active = False
self.color = active_color if self.active else inactive_color

if event.type == pygame.KEYDOWN:
if self.active:
if event.key == pygame.K_RETURN:
self.text = ''
elif event.key == pygame.K_BACKSPACE:
self.text = self.text[:-1]
else:
self.text += event.unicode

def draw(self,screen):
pygame.draw.rect(screen, self.color, self.rect, 1)
drawTextRect = self.rect.inflate(-5, -5)
drawText(screen, self.text, self.color, drawTextRect, font, textAlignLeft, True)

def update(self):
pass

back_rect = pygame.Rect(30,30,45,45)

inputbox = InputBox(15,180,305,140,96)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
inputbox.event_handler(event)

screen.fill(0)

inputbox.update()
inputbox.draw(screen)
pygame.display.update()
app_fps.tick(60)


Related Topics



Leave a reply



Submit