0
\$\begingroup\$

I want a text box to appear on the screen. I am doing this by:

TextButton= pygame.draw.rect(Screen,Red, (100, 100, 150,50),2)

How can I allow the user to enter a text into this text box in Pygame? The text box should say 'Enter your name here'. When the user clicks on it, they should be able to enter their name, and submit it if the textbox is not empty. How can I do this in pygame?

\$\endgroup\$
1
\$\begingroup\$

Pygame does not support this feature. Usually this sort of thing is handled by GUI libraries, but I'm not aware of any that works with pygame, so I think you have to build it yourself. Here's what you need to do:

  • Keep a string for user input
  • Draw that string, and whatever else you need for the text box
  • When the user has pressed a key:
    • If it's a character, add it to the string
    • If it's a special key like backspace, delete the last character

That gives you the bare minimum, if you want other features like movable cursor, you need to write more code.

\$\endgroup\$
0
\$\begingroup\$

Here is some code I use in my game. It's not exactly what you asked for, but it's close.

import pygame
pygame.init()
validChars = "`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./"
shiftChars = '~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?'

class TextBox(pygame.sprite.Sprite):
  def __init__(self):
    pygame.sprite.Sprite.__init__(self)
    self.text = ""
    self.font = pygame.font.Font(None, 50)
    self.image = self.font.render("Enter your name", False, [0, 0, 0])
    self.rect = self.image.get_rect()

  def add_chr(self, char):
    global shiftDown
    if char in validChars and not shiftDown:
        self.text += char
    elif char in validChars and shiftDown:
        self.text += shiftChars[validChars.index(char)]
    self.update()

  def update(self):
    old_rect_pos = self.rect.center
    self.image = self.font.render(self.text, False, [0, 0, 0])
    self.rect = self.image.get_rect()
    self.rect.center = old_rect_pos


screen = pygame.display.set_mode([640, 480])
textBox = TextBox()
shiftDown = False
textBox.rect.center = [320, 240]

running = True
while running:
  screen.fill([255, 255, 255])
  screen.blit(textBox.image, textBox.rect)
  pygame.display.flip()
  for e in pygame.event.get():
    if e.type == pygame.QUIT:
        running = False
    if e.type == pygame.KEYUP:
        if e.key in [pygame.K_RSHIFT, pygame.K_LSHIFT]:
            shiftDown = False
    if e.type == pygame.KEYDOWN:
        textBox.add_chr(pygame.key.name(e.key))
        if e.key == pygame.K_SPACE:
            textBox.text += " "
            textBox.update()
        if e.key in [pygame.K_RSHIFT, pygame.K_LSHIFT]:
            shiftDown = True
        if e.key == pygame.K_BACKSPACE:
            textBox.text = textBox.text[:-1]
            textBox.update()
        if e.key == pygame.K_RETURN:
            if len(textBox.text) > 0:
                print (textBox.text)
                running = False
pygame.quit()
\$\endgroup\$
1
  • \$\begingroup\$ If it's not exactly what they asked for, this isn't a valid answer to the question. Yet, if it's close you could work out the code a little bit and propose a minimal solution to the question. \$\endgroup\$ – liggiorgio Jun 23 '18 at 15:06
-1
\$\begingroup\$

you can try this code

import pygame
vec = pygame.math.Vector2
class Text_box:
def __init__(self, x, y, width, height, bg_colour=(124, 124, 124), active_colour=(255,255,255),
             text_size=24, text_colour=(0,0,0), border=0, border_colour=(0,0,0)):
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.pos = vec(x, y)
    self.size = vec(width, height)
    self.image = pygame.Surface((width, height))
    self.bg_colour = bg_colour
    self.active_colour = active_colour
    self.active = False
    self.text = ""
    self.text_size = text_size
    self.font = pygame.font.SysFont("Times New Roman", self.text_size)
    self.text_colour = text_colour
    self.border_colour = border_colour
    self.border = border
    self.numbers = [48,49,50,51,52,53,54,55,56,57]
    self.special = [8,32]

def update(self):
    pass

def draw(self, gameDisplay):
    if not self.active:
        self.text = "Enter your name"
        if self.border == 0:
            self.image.fill(self.bg_colour)
        else:
            self.image.fill(self.border_colour)
            pygame.draw.rect(self.image, self.bg_colour,
                             (self.border, self.border, self.width-self.border*2,
                              self.height-self.border*2))

        text = self.font.render(self.text, False, self.text_colour)
        text_height = text.get_height()
        self.image.blit(text, (self.border*2, (self.height-text_height)//2))
    else:
        if self.border == 0:
            self.image.fill(self.active_colour)
        else:
            self.image.fill(self.border_colour)
            pygame.draw.rect(self.image, self.active_colour,
                             (self.border, self.border, self.width-self.border*2,
                              self.height-self.border*2))
            if self.text == "Enter your name":
                self.text = ""
            else:
                text = self.font.render(self.text, False, self.text_colour)
                text_height = text.get_height()
                text_width = text.get_width()
                if text_width < self.width-self.border*2:
                    self.image.blit(text, (self.border*2,(self.height-text_height)//2))
                else:
                    self.image.blit(text, ((self.border*2)+(self.width-text_width-self.border*3),(self.height-text_height)//2))        

    gameDisplay.blit(self.image, self.pos)

def add_text(self, key):
    try:
        if chr(key).isalpha():
            text = list(self.text)
            text.append(chr(key))
            self.text = ''.join(text)
            print(self.text)
        elif key == 8:
            text = list(self.text)
            text.pop()
            self.text = ''.join(text)
        #for space
        #elif key == 32:
            #text = list(self.text)
            #text.append(' ')
            #self.text = ''.join(text)
        else:
            print(key)
    except:
        print(key)

def check_click(self, pos):
    if pos[0] > self.x and pos[0] < self.x+self.width:
        if pos[1] > self.y and pos[1] < self.y+self.height:
            self.active = True
        else:
            self.active = False
    else:
        self.active = False

def return_value(self):
    return self.text
\$\endgroup\$
1
  • 1
    \$\begingroup\$ This answer would be even better if it included an explanation of how & why this code solves the problem. \$\endgroup\$ – DMGregory Mar 4 '20 at 4:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.