Search code examples
pythonpygame-menu

How can a textbox in pygame_menu be cleared automatically when activating the textbox?


I'm trying to create a form on pygame that takes player input.

I'm using the pygame_menu library to create the input form and part of it is a textbox input.

I'd like to set the textbox up so that when the player clicks on the textbox to enable entry, it automatically clears the box however what I have currently doesn't work and either gives an error, or doesn't clear the box leaving the existing value in there.

I've tried using the command on_select= to call a "clear textbox" function

The most concise code that runs is below. The textbox in question is between ###

import pygame
import pygame_menu as pm
import sys

from pygame.locals import *

WIDTH, HEIGHT = 1100, 800
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.init()

def clear_text(name):
    name = ""

def first_name(name):
    print(name)

my_theme = pm.themes.THEME_DARK.copy()
my_theme.title = False
my_theme.background_color = color_opaque = (50, 100, 200)

    
setup_menu = pm.Menu('', WIDTH, HEIGHT)

####
firstnametxtbox = setup_menu.add.text_input('', textinput_id="FirstNameInput", default='First Name', maxchar=10, onselect=clear_text, onreturn=first_name)
####

def main():
    run = True
    clock = pygame.time.Clock()

    while run:
        clock.tick(60)

        for event in pygame.event.get():
            if event.type == QUIT:
                run = False
                pygame.display.quit()
                pygame.quit
                sys.exit()
                break

            if setup_menu.is_enabled():
                setup_menu.update(pygame.event.get())
                setup_menu.mainloop(WIN)
            

            pygame.display.update()

if __name__ == "__main__":
    main() 

Typing in the textbox and pressing enter prints the name however clicking the box doesn't remove the existing name? The error received is that the function is expecting a positional argument however that's not what happens when return is pressed?

I'm expecting the textbox to clear on selection


Solution

  • The onselect call back function is predefined as having three parameters passed to it

    onselect(selected, widget, menu), where selected is a boolean representing the selected status:

    So your callback function has to have those three parameters, where widget represents the textField, and you can use its get_value() and set_value(new_value) methods to check and change the current value

    Changing your clear_text callback function definition to the following should work:

    def clear_text(selected, widget, menu):
        if selected and widget.get_value() == widget._default_value:
            widget.set_value('')
        elif widget.get_value().strip() == '':
            widget.set_value(widget._default_value)
    

    From playing around with this a bit, I recommend setting the title parameter of the textField widget to something other than the empty string, otherwise the field seems to vanish if you just clear it out and don't reset the default as I added here. I couldn't find the setting to set a minimum width for the textField only the maximum width, although that feels like it should be a basic setting.