How to allow the user to type only under certain conditions in pygame? [duplicate]

落爺英雄遲暮 提交于 2020-11-25 03:41:38

问题


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)

回答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)  



回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/64254687/how-to-allow-the-user-to-type-only-under-certain-conditions-in-pygame

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!