1

When you click the textbox I want the user to be able to type letters by setting self.active to True. When you click off the text box I want the player to lose that ability by setting self.active to False. However when I click the text box, self.active becomes true for a split second before becoming False again. How do I fix this?

from pygame import *

init()
screen = display.set_mode((800, 600))

name_font = font.Font(None, 32)
name_text = ''


class Rectangle:

    def __init__(self, x, y):
        self.active = False
        self.x = x
        self.y = y
        self.text_surface = name_font.render(name_text, 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)
        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))

    def naming(self):
        global rect_1
        global name_text

        if events.type == MOUSEBUTTONDOWN:
            if self.input_rect.x + 150 >= mx >= self.input_rect.x - 10:
                if self.input_rect.y + 40 >= my >= self.input_rect.y - 10:
                    self.active = True
            if not self.input_rect.x + 150 >= mx >= self.input_rect.x - 10:
                if not self.input_rect.y + 40 >= my >= self.input_rect.y - 10:
                    self.active = False

        if self.active:
            if events.type == KEYDOWN:
                if keys[K_BACKSPACE]:
                    name_text = name_text[:-1]
                    screen.fill((0, 0, 0))
                    rect_1 = Rectangle(200, 200)
                else:
                    name_text += events.unicode


while True:
    rect_1 = Rectangle(200, 200)
    mx, my = mouse.get_pos()
    for events in event.get():
        keys = key.get_pressed()
        rect_1.naming()
        if events.type == QUIT:
            quit()

    display.update()
    time.delay(1)
mr. bug
  • 309
  • 1
  • 11

3 Answers3

1

Create the instance of Rectangle before the application loop, but you have to pass the list of events to the method naming and to handle all the relevant events in the method. Add a draw method to the class and draw the object in every frame:

class Rectangle:
    # [...]

    def naming(self, events):
        # [...]

        for event in evetnts:
            if e.type == KEYDOWN:
                # [...]

        
            if e.type == # [...]

    def draw(self, screen):
        # [...]
rect_1 = Rectangle(200, 200)

run = True
while run :
    
    events = event.get()
    for e in events:
        if e.type == QUIT:
            run = False
    
    rect_1.naming(events)

    # [...]

    rect_1.draw(screen)      

Complete example:

import pygame
from pygame import *

init()
screen = display.set_mode((800, 600))

name_font = font.Font(None, 32)
name_text = ''


class Rectangle:

    def __init__(self, x, y):
        self.active = False
        self.x = x
        self.y = y
        self.text_surface = name_font.render(name_text, 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)
        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))

    def naming(self, events):
        global rect_1
        global name_text

        for e in events:
            if e.type == MOUSEBUTTONDOWN:
                mx, my = e.pos
                if self.input_rect.x + 150 >= mx >= self.input_rect.x - 10:
                    if self.input_rect.y + 40 >= my >= self.input_rect.y - 10:
                        self.active = True
                if not self.input_rect.x + 150 >= mx >= self.input_rect.x - 10:
                    if not self.input_rect.y + 40 >= my >= self.input_rect.y - 10:
                        self.active = False

            if e.type == KEYDOWN:
                if self.active:
                    if e.key == K_BACKSPACE:
                        name_text = name_text[:-1]
                    else:
                        name_text += e.unicode
                    self.text_surface = name_font.render(name_text, 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)

run = True
while run :
    
    events = event.get()
    for e in events:
        if e.type == QUIT:
            run = False
    
    rect_1.naming(events)

    screen.fill(0)
    rect_1.draw(screen)  
    display.update()
    time.delay(1)  
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
0

It looks to me like you need to take line 47 "rect_1 = Rectangle(200, 200)" out of the while loop because you keep recreating the box and it instantiates a new box with an active value equal to false.

  • @Python2019 is mistaken mx and my are updated and compared when the mouse is clicked he doesn't get them with global but he still uses them. I have run the code the box actives when click and deactivates when another click outside of it happens when you change what I said before. – 20smcnamara Oct 08 '20 at 02:55
0

You are getting the mouse position but not doing anything with it like comparing it to the location of the box. if you start with self.active = True you can type in the box regardless of where the cursor is.

Python2019
  • 33
  • 7