为什么我的按钮在主循环之外不起作用

Why does my button not work outside of the main loop

我一直在关注 this tutorial pygame 中的动画按钮。在我在另一个函数的主循环之外创建一个按钮之前,它工作得很好。

这是我的代码:

import pygame
from pygame.locals import *
import sys
import random

# Constants

SCREEN = pygame.display.set_mode((1280, 720), 0, 32)

# Colours
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREY = (100, 100, 100)
LIGHT_BLUE = (66, 233, 245)

# Button Class
class Button:
    def __init__(self, text, width, height, pos, elevation):
        # Core attributes
        self.pressed = False
        self.elevation = elevation
        self.dynamicElevation = elevation
        self.originalYPos = pos[1]

        # Top Rectangle
        self.topRectangle = pygame.Rect(pos, (width, height))
        self.topColor = '#457B9D'

        # Bottom Rectangle
        self.bottomRectangle = pygame.Rect(pos, (width, elevation))
        self.bottomColor = '#1D3557'

        # Text
        self.textSurface = gui_font.render(text, True, '#FFFFFF')
        self.textRectangle = self.textSurface.get_rect(center = self.topRectangle.center)

    def draw(self):
        # Elevation Logic
        self.topRectangle.y = self.originalYPos - self.dynamicElevation
        self.textRectangle.center = self.topRectangle.center

        self.bottomRectangle.midtop = self.topRectangle.midtop
        self.bottomRectangle.height = self.topRectangle.height + self.dynamicElevation

        bottom =pygame.draw.rect(SCREEN, self.bottomColor, self.bottomRectangle, border_radius = 12)
        top = pygame.draw.rect(SCREEN, self.topColor, self.topRectangle, border_radius = 12)
    
        pygame.draw.rect(SCREEN, '#000000', top, 1, border_radius = 12)
        pygame.draw.rect(SCREEN, '#000000', bottom, 1, border_radius = 12)
    
        SCREEN.blit(self.textSurface, self.textRectangle)
        self.check_click()

    def check_click(self):
        mousePosition = pygame.mouse.get_pos()
        if self.topRectangle.collidepoint(mousePosition):
            self.topColor = '#F1FAEE'
            if pygame.mouse.get_pressed()[0]:
                self.dynamicElevation = 0
                self.pressed = True
            else:
                self.dynamicElevation = self.elevation
                if self.pressed == True:
                    print("Click")
                    self.pressed = False
        else:
            self.topColor = '#457B9D'

class GameState():
    def __init__(self):
        self.state = "welcome"

    def welcomeScreen(self):
        SCREEN.fill(WHITE)
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    exit()
                if event.key == K_F1:
                    self.state = "mainGame"

        pygame.display.update()


    def mainGame(self):
        SCREEN.fill(GREY)
        buttonBack = Button("Back to Main Screen", 250, 30, (1000, 650), 8)

        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    exit()
                if event.key == K_F2:
                    self.state = "welcome"

        buttonBack.draw()
        pygame.display.update()

    def stateManager(self):
        if self.state == "welcome":
            self.welcomeScreen()
        if self.state == "mainGame":
            self.mainGame()




pygame.init()
clock = pygame.time.Clock()
gameState = GameState()

pygame.display.set_caption("Button Test")

gui_font = pygame.font.Font(None, 30)

while True:

    gameState.stateManager()
    clock.tick(60)

我试过将按钮放在不同的屏幕或循环的不同阶段。是否存在我看不到的逻辑错误或其他地方的错误?

您实际上是在主循环内创建按钮,因为您每次调用 mainGame 时都会创建它。 mainGame 如果状态为“mainGame”,则由 stateManager 调用,并且会在 while True 循环中的每一帧调用。所以当你在每一帧重新创建你的按钮时,我认为你的问题可能来自那里。

我建议您改为在父级的 class 构造函数中创建按钮:

class GameState():
    def __init__(self):
        self.state = "welcome"
        # Create the button here to make the object persistent.
        self.buttonBack = Button("Back to Main Screen", 250, 30, (1000, 650), 8)
    # ...

    def mainGame(self):
        SCREEN.fill(GREY)

        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    exit()
                if event.key == K_F2:
                    self.state = "welcome"

        self.buttonBack.draw() # <- use your button with self.buttonBack
        pygame.display.update()
     # ...