'While loop only iterating once through nested classes

I'm building a chess gui using pygame, in which the main game loop calls a method in a seperate class (Move in GameState class), which then further calls another method in the same class(pawn_promotion). In the pawn_promotion method, a surface, promotion_menu, is being blit into the window.

But it only appears on screen for one frame. Please correct me if I'm wrong here but what I think is happening is that the surface is being blit but when the game loop iterates again it gets covered up with the chess board being blit onto to the window.

class GameWindow:
    def __init__(self):
        load()
        gs = GameState()
        m = MoveList
        run = True
        square_selected = ()
        clicks = []
        while run:
            win.blit(board_surface, (467, 132))
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        MainMenu()
                        run = False
                # Mouse ui
                if event.type == pygame.MOUSEBUTTONDOWN:  # checking for clicks
                    location = (pygame.mouse.get_pos()[0] - 467, pygame.mouse.get_pos()[1] - 132)
                    if 600 >= location[0] >= 0 and 600 >= location[1] >= 0:
                        column = location[0] // Square_size
                        row = location[1] // Square_size
                    # checking for repeat clicks
                        if square_selected == (row, column):
                            square_selected = ()
                            clicks = []  # if click is repeat, clear previous click
                        else:
                            # Player selects a square
                            square_selected = (row, column)
                            clicks.append(square_selected)

                        if len(clicks) == 2:
                            # second click moves the piece
                            self.move = m(clicks[0], clicks[1], gs.board)
                            gs.Move(self.move)
                            square_selected = ()
                            clicks = []
                            if gs.close_window:
                                run = False
class GameState:
...irrelavant code...
    def pawn_promotion(self, move):
        print(move.endrow, move.endcol)
        self.is_prmt = True
        promotion_menu = pygame.Surface((int(Square_size), int(Square_size * 4)))
        promotion_menu.fill(white)
        prmt_confirm = ''
        if self.white_turn:
            prmt_white_queen = Button(board_surface, (move.endcol + 1) * Square_size, 50, pieces_dict['wQ'], 1)
            prmt_white_rook = Button(board_surface, (move.endcol + 1) * Square_size, 50 + Square_size,
                                     pieces_dict['wR'], 1)
            prmt_white_knight = Button(board_surface, (move.endcol + 1) * Square_size, 50 + (2 * Square_size),
                                       pieces_dict['wN'], 1)
            prmt_white_bishop = Button(board_surface, (move.endcol + 1) * Square_size, 50 + (3 * Square_size),
                                       pieces_dict['wB'], 1)

            if self.run_promote_menu:
                print(self.run_promote_menu)
                board_surface.blit(promotion_menu, ((move.endcol + 1) * Square_size, (move.endrow * Square_size) + 50))
                prmt_queen = Button.draw(prmt_white_queen)
                prmt_rook = Button.draw(prmt_white_rook)
                prmt_knight = Button.draw(prmt_white_knight)
                prmt_bishop = Button.draw(prmt_white_bishop)

                if prmt_queen:
                    prmt_confirm = 'wQ'
                    # run_promote_menu = False
                if prmt_rook:
                    prmt_confirm = 'wR'
                    # run_promote_menu = False
                if prmt_knight:
                    prmt_confirm = 'wN'
                    # run_promote_menu = False
                if prmt_bishop:
                    prmt_confirm = 'wB'
                    # run_promote_menu = False
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        self.run_promote_menu = False
                        close_window = True
                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_z:
                            self.run_promote_menu = False
                if prmt_confirm != '':
                    self.run_promote_menu = False
                    self.board[move.endrow][move.endcol] = prmt_confirm
                pygame.display.update()

I'm creating 4 buttons on the surface using the following class

class Button:
    def __init__(self, surface, x, y, image, scale):
        image_width = image.get_width()
        image_height = image.get_height()
        self.image = pygame.transform.scale(image, (int(image_width * scale), int(image_height * scale)))
        self.image_rect = image.get_rect(topleft=(x, y))
        self.surface = surface
        self.clicked = False
        self.image_bg = pygame.Surface((self.image_rect.width + 10, self.image_rect.height + 5))
        self.image_bg.set_alpha(0)

    def draw(self):
        action = False
        pos = pygame.mouse.get_pos()
        if self.image_rect.collidepoint(pos):
            self.image_bg.set_alpha(1)
            for event in pygame.event.get():
                if pygame.mouse.get_pressed()[0] == 1 and not self.clicked:
                    self.clicked = True
                    action = True
                if pygame.mouse.get_pressed()[1] == 0:
                    self.clicked = False
        else:
            self.image_bg.set_alpha(0)
        self.surface.blit(self.image_bg, (self.image_rect.x - 5, self.image_rect.y))
        self.surface.blit(self.image, (self.image_rect.x, self.image_rect.y))
        return action

I'm having another small issue with this class, the set_alpha() lines seem to be increasing value of alpha each frame rather than setting it to a constant value. Is there another command for keeping alpha constant?

If I use a while loop inside pawn_promotion, it works perfectly but since it's essentially two nested while loops, it creates a lot of lag. I tried to reduce this lag by using clock.tick() but it doesn't get rid of it entirely.



Sources

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

Source: Stack Overflow

Solution Source