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)
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:
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
How to Pad a String With Zeroes
How to Use Subprocess.Popen to Connect Multiple Processes by Pipes
How to Use Glob() to Find Files Recursively
Prevent Scientific Notation in Matplotlib.Pyplot
List Comprehension on a Nested List
What Is the Python Keyword "With" Used For
Do Regular Expressions from the Re Module Support Word Boundaries (\B)
How to Fill Out a Python String With Spaces
Understanding Repr( ) Function in Python
How to Have One Colorbar For All Subplots
Why Do Python Classes Inherit Object
Does Python Have "Private" Variables in Classes
Importerror: No Module Named 'Pygame'