1

I want the user to be able to type a name into each of the 2 textboxes when they click on them. Instead what happens is the next letter will always replace the previous letter instead of writing out a new letter onto the screen. For example, if you try to type "mat" then the a will replace the m and the t will replace the a. How do I fix this?

from pygame import *

screen_width = 1400
screen_height = 800

init()
screen = display.set_mode((screen_width, screen_height))

name_font = font.Font(None, 32)
name_1 = ""
name_2 = ""


class Rectangle:

    def __init__(self, x, y):
        self.name = ""
        self.active = False
        self.x = x
        self.y = y

        self.text_surface = name_font.render(self.name, True, (255, 255, 255))
        self.rect_width = max(140, 10 + self.text_surface.get_width())
        self.input_rect = Rect(x, y, self.rect_width, 32)
        self.input_rect.w = self.text_surface.get_width() + 10
        self.click_value = 10

    def naming(self, player_name):

        for e in events:
            if e.type == MOUSEBUTTONDOWN:
                if self.input_rect.x + self.click_value >= mx >= self.input_rect.x - 10 and self.input_rect.y + 26 >= my >= self.input_rect.y - 10:
                    self.active = True
                else:
                    self.active = False

            if e.type == KEYDOWN:
                if self.active:
                    if e.key == K_BACKSPACE:
                        player_name = player_name[:-1]
                        screen.fill((0, 0, 0))
                    else:
                        player_name += e.unicode
                        self.click_value += 7

                    self.text_surface = name_font.render(player_name, True, (255, 255, 255))

    def draw(self, screen):
        draw.rect(screen, (0, 0, 0), self.input_rect, 0)
        draw.rect(screen, (255, 255, 255), self.input_rect, 2)
        self.input_rect.w = self.text_surface.get_width() + 10
        screen.blit(self.text_surface, (self.input_rect.x + 5, self.input_rect.y + 5))


rect_1 = Rectangle(200, 200)

rect_2 = Rectangle(200, 400)

while True:
    mx, my = mouse.get_pos()

    events = event.get()
    for e in events:
        if e.type == QUIT:
            quit()

    screen.fill((0, 0, 0))
    rect_1.naming(name_1)
    rect_1.draw(screen)

    rect_2.naming(name_2)
    rect_2.draw(screen)

    display.update()
    time.delay(1)

I think it has something to do with the placement of the name_1 and name_2 variables but I'm not entirely sure.

mr. bug
  • 309
  • 1
  • 11

2 Answers2

1

You can use this code:-

import pygame
import sys

pygame.init()

clock = pygame.time.Clock()

# it will display on screen
screen = pygame.display.set_mode([600, 500])

# basic font for user typed
base_font = pygame.font.Font(None, 32)
user_text = ''

# create rectangle
input_rect = pygame.Rect(200, 200, 140, 32)

# color_active stores color(lightskyblue3) which
# gets active when input box is clicked by user
color_active = pygame.Color('lightskyblue3')

# color_passive store color(chartreuse4) which is
# color of input box.
color_passive = pygame.Color('chartreuse4')
color = color_passive

active = False

while True:
    for event in pygame.event.get():

    # if user types QUIT then the screen will close
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.MOUSEBUTTONDOWN:
            if input_rect.collidepoint(event.pos):
                active = True
            else:
                active = False

        if event.type == pygame.KEYDOWN:

            # Check for backspace
            if event.key == pygame.K_BACKSPACE:

                # get text input from 0 to -1 i.e. end.
                user_text = user_text[:-1]

            # Unicode standard is used for string
            # formation
            else:
                user_text += event.unicode
    
    # it will set background color of screen
    screen.fill((255, 255, 255))

    if active:
        color = color_active
    else:
        color = color_passive
        
    # draw rectangle and argument passed which should
    # be on screen
    pygame.draw.rect(screen, color, input_rect)

    text_surface = base_font.render(user_text, True, (255, 255, 255))
    
    # render at position stated in arguments
    screen.blit(text_surface, (input_rect.x+5, input_rect.y+5))
    
    # set width of textfield so that text cannot get
    # outside of user's text input
    input_rect.w = max(100, text_surface.get_width()+10)
    
    # display.flip() will update only a portion of the
    # screen to updated, not full area
    pygame.display.flip()
    
    # clock.tick(60) means that for every second at most
    # 60 frames should be passed.
    clock.tick(60)

1

Pyhton has not concept of in-out parameters. Use the self.name attribute, instead of an argument:

from pygame import *

screen_width = 1400
screen_height = 800

init()
screen = display.set_mode((screen_width, screen_height))

name_font = font.Font(None, 32)
name_1 = ""
name_2 = ""

class Rectangle:

    def __init__(self, x, y):
        self.name = ""
        self.active = False
        self.x = x
        self.y = y

        self.text_surface = name_font.render(self.name, True, (255, 255, 255))
        self.rect_width = max(140, 10 + self.text_surface.get_width())
        self.input_rect = Rect(x, y, self.rect_width, 32)
        self.input_rect.w = self.text_surface.get_width() + 10
        self.click_value = 10

    def naming(self):

        for e in events:
            if e.type == MOUSEBUTTONDOWN:
                if self.input_rect.x + self.click_value >= mx >= self.input_rect.x - 10 and self.input_rect.y + 26 >= my >= self.input_rect.y - 10:
                    self.active = True
                else:
                    self.active = False

            if e.type == KEYDOWN:
                if self.active:
                    if e.key == K_BACKSPACE:
                        self.name = self.name[:-1]
                        screen.fill((0, 0, 0))
                    else:
                        self.name += e.unicode
                        self.click_value += 7

                    self.text_surface = name_font.render(self.name, True, (255, 255, 255))
        return self.name

    def draw(self, screen):
        draw.rect(screen, (0, 0, 0), self.input_rect, 0)
        draw.rect(screen, (255, 255, 255), self.input_rect, 2)
        self.input_rect.w = self.text_surface.get_width() + 10
        screen.blit(self.text_surface, (self.input_rect.x + 5, self.input_rect.y + 5))


rect_1 = Rectangle(200, 200)

rect_2 = Rectangle(200, 400)

while True:
    mx, my = mouse.get_pos()

    events = event.get()
    for e in events:
        if e.type == QUIT:
            quit()

    screen.fill((0, 0, 0))
    name_1 = rect_1.naming()
    rect_1.draw(screen)

    name_2 = rect_2.naming()
    rect_2.draw(screen)

    display.update()
    time.delay(1)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174