'Why do I get an Recursion error whenever i am deleting a letter from a modified stirng And how do I solve it?

I am trying to make a choice game where you can write and rewrite a name of the character in the game but whenever I try to delete a letter whilst testing the code I get an Recursion error What is the cause to this problem and how to avoid it?

Here is my code

import pygame as pg
pg.init()
import time
win = pg.display.set_mode((900,600))
pg.display.set_caption("Choices")
go = 0
user_text = ''
lbrown = 225, 156, 0
brown = 192, 128, 0
dbrown = 128, 64, 0
black = 0, 0, 0
dgrey = 64, 64, 64
grey = 128,128,128
lgrey = 192,192,192
white = 255, 255, 255
red = 255, 0, 0
orange = 255,128,0
yellow = 255,223,0
lgreen = 128,255,0
green = 0,255,0
dgreen = 0,128,0
turcoise = 0,192,128
lblue = 0,128,255
blue = 0,0,255
dblue = 0,0,128
blurple = 128,0,192
purple = 192,0,192
pirple = 167, 0, 167
rpink = 255,0,128
pink = 255,0,255
startclick = 0

class BG(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface([400,100])
        self.image.fill(white)
        self.rect = self.image.get_rect()

class START(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface([200,100])
        self.image.fill(green)
        self.rect = self.image.get_rect()

class START_TEXT(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        font = pg.font.SysFont('Comic Sans MS', 40)
        self.image = font.render('Start',False, pink)
        self.rect = self.image.get_rect()



bg = BG()
bg.rect.x = 25
bg.rect.y = 100

start = START()
start.rect.x = 450
start.rect.y = 260

start_txt = START_TEXT()
start_txt.rect.x = 495
start_txt.rect.y = 280

all_sprite = pg.sprite.Group()
all_sprite.add(start,start_txt)


win.fill(purple)

def redraw():
    all_sprite.draw(win)
    pg.display.update()

run = True
while run:
    pos = pg.mouse.get_pos()
    print(startclick)


    for event in pg.event.get():
        if event.type == pg.QUIT:
            run = False

        if start.rect.collidepoint(pos):
            start.image.fill(dgreen)
            if event.type == pg.MOUSEBUTTONDOWN:
                startclick = 1

                win.fill(black)
                all_sprite.remove(start,start_txt)
        else:
            start.image.fill(green)

        key = pg.key.get_pressed()
        if key[pg.K_BACKSPACE]:
            all_sprite.remove(bg, user_text)
            user_text = user_text[:-1]

            go = 1
        else:
            if event.type == pg.KEYDOWN:
                user_text += event.unicode
            usertex = user_text

        class User_TxT(pg.sprite.Sprite):
            def __init__(self):
                pg.sprite.Sprite.__init__(self)
                font = pg.font.SysFont('Comic Sans MS', 40)
                self.image = font.render(usertex, True, pink)
                self.rect = self.image.get_rect()

        user_txt = User_TxT()
        user_txt.rect.x = 70
        user_txt.rect.y = 120

        if startclick == 1:
            all_sprite.add(bg, user_txt)



    pg.display.flip()
    redraw()
quit()
pg.quit()

And the Recursion Error

packages\pygame\sprite.py", line 471, in
    if isinstance(sprite, Sprite):        
RecursionError: maximum recursion depth exceeded while calling a Python object

Why is this happening?



Solution 1:[1]

I've modified your User_TxT sprite class to support an update function to change its text. This will prevent the need to remove and recreate the sprite which causes your recursion error.

import pygame as pg
pg.init()
import time
win = pg.display.set_mode((900,600))
pg.display.set_caption("Choices")
go = 0
user_text = ''
lbrown = 225, 156, 0
brown = 192, 128, 0
dbrown = 128, 64, 0
black = 0, 0, 0
dgrey = 64, 64, 64
grey = 128,128,128
lgrey = 192,192,192
white = 255, 255, 255
red = 255, 0, 0
orange = 255,128,0
yellow = 255,223,0
lgreen = 128,255,0
green = 0,255,0
dgreen = 0,128,0
turcoise = 0,192,128
lblue = 0,128,255
blue = 0,0,255
dblue = 0,0,128
blurple = 128,0,192
purple = 192,0,192
pirple = 167, 0, 167
rpink = 255,0,128
pink = 255,0,255
startclick = 0

class BG(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface([400,100])
        self.image.fill(white)
        self.rect = self.image.get_rect()

class START(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface([200,100])
        self.image.fill(green)
        self.rect = self.image.get_rect()

class START_TEXT(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        font = pg.font.SysFont('Comic Sans MS', 40)
        self.image = font.render('Start',False, pink)
        self.rect = self.image.get_rect()

class User_TxT(pg.sprite.Sprite):
    def __init__(self, usertex):
        pg.sprite.Sprite.__init__(self)
        self.update(usertex)
    
    def update(self, usertex):
        font = pg.font.SysFont('Comic Sans MS', 40)
        self.image = font.render(usertex, True, pink)
        self.rect = self.image.get_rect()

bg = BG()
bg.rect.x = 25
bg.rect.y = 100

start = START()
start.rect.x = 450
start.rect.y = 260

start_txt = START_TEXT()
start_txt.rect.x = 495
start_txt.rect.y = 280


user_txt = User_TxT(user_text)

all_sprite = pg.sprite.Group()
all_sprite.add(start,start_txt)


win.fill(purple)

def redraw():
    all_sprite.draw(win)
    pg.display.update()

run = True
while run:
    pos = pg.mouse.get_pos()
    print(startclick)
    for event in pg.event.get():
        if event.type == pg.QUIT:
            run = False

        if start.rect.collidepoint(pos):
            start.image.fill(dgreen)
            if event.type == pg.MOUSEBUTTONDOWN:
                startclick = 1

                win.fill(black)
                all_sprite.remove(start,start_txt)
        else:
            start.image.fill(green)

        key = pg.key.get_pressed()
        if key[pg.K_BACKSPACE]:
            # all_sprite.remove(bg, user_text)
            user_text = user_text[:-1]

            go = 1
        else:
            if event.type == pg.KEYDOWN:
                user_text += event.unicode
            # usertex = user_text
        user_txt.update(user_text)

        user_txt.rect.x = 70
        user_txt.rect.y = 120

        if startclick == 1:
            all_sprite.add(bg, user_txt)
            startclick = 0

    pg.display.flip()
    redraw()
quit()
pg.quit()

I've tried to make minimal changes to your code to avoid confusion.

EDIT to add some additional explanation: I changed the User_TxT sprite class to take an input string as its initial text string to display and to also have an update() function so that its text string can be changed. This function is also what we need to do when initialising the sprite, so to prevent duplication, it's called from __init__(). That way you only need to have one sprite. You were also redefining and instantiating the User_TxT class for every event, which is unnecessary.

To help identify the code differences, you can use a diff tool, like WinMerge on Windows, or the command line diff tool on Linux.

If you run into further issues with your code, you should ask a new question, if you create a Minimal, Reproducible Example it will make it easier to help you.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1