¿Cómo implemento botones de opción y cambio el color del botón en PyGame?

Nov 29 2020

Por favor, sugiera cómo puedo cambiar el color del botón cuando lo presioné, y el color del primer botón cambiará al color predeterminado cuando presione el segundo botón.

Por ejemplo, después de hacer clic en el botón RECTO, el botón se volverá de color verde y cuando hago clic en el botón IZQUIERDO, el botón IZQUIERDO cambiará a color verde y el botón RECTO se convertirá en el color predeterminado, que es el color blanco. Gracias por adelantado :)

CÓDIGO:

def draw_button(self):

    global clicked
    action = False

    # get mouse position
    pos = pygame.mouse.get_pos()

    # create pygame Rect object for the button
    button_rect = Rect(self.x, self.y, self.width, self.height)

    # check mouseover and clicked conditions
    if button_rect.collidepoint(pos):
        if pygame.mouse.get_pressed()[0] == 1:
            clicked = True
            pygame.draw.rect(screen, self.click_col, button_rect)
        elif pygame.mouse.get_pressed()[0] == 0 and clicked == True:
            clicked = False
            action = True
           
        else:
            pygame.draw.rect(screen, self.hover_col, button_rect)
    else:
        pygame.draw.rect(screen, self.button_col, button_rect)

Respuestas

1 Rabbid76 Nov 29 2020 at 19:01

Cuando dibuja el botón, debe establecer el color en función de la variable global clicked:

def draw_button(self):

    global clicked
    
    # get mouse position
    pos = pygame.mouse.get_pos()

    # create pygame Rect object for the button
    button_rect = Rect(self.x, self.y, self.width, self.height)

    # check mouseover and clicked conditions
    hover = button_rect.collidepoint(pos)
    if hover and pygame.mouse.get_pressed()[0] == 1:
        clicked = not clicked

    color = self.button_col
    if clicked:
        color = self.click_col
    elif hover:
        color = self.hover_col

    pygame.draw.rect(screen, color, button_rect)

De todos modos, eso no te satisfará, porque pygame.mouse.get_pressed()devuelve una lista de valores booleanos que representan el estado ( Trueo False) de todos los botones del mouse. El estado de un botón es Truesiempre que se mantenga pulsado un botón.
Tienes que usar MOUSEBUTTONDOWNevent. El MOUSEBUTTONDOWNevento ocurre una vez cuando hace clic con el botón del mouse y el MOUSEBUTTONUPevento ocurre una vez cuando se suelta el botón del mouse. El pygame.event.Event()objeto tiene dos atributos que proporcionan información sobre el evento del mouse. poses una tupla que almacena la posición en la que se hizo clic. buttonalmacena el botón en el que se hizo clic.


Si tiene varios botones que deben interactuar entre sí, un solo clickedestado no es suficiente. Necesita un estado de "clic" separado para cada botón. Si el estado en el que se hizo clic en el botón 1 pasa a ser True, los estados de las otras teclas deben establecerse en False. Recomiendo implementar una RadioButtonclase para esto.

Consulte también Mouse y Sprite .

Ejemplo mínimo:

import pygame

class RadioButton(pygame.sprite.Sprite):
    def __init__(self, x, y, w, h, font, text):
        super().__init__() 
        text_surf = font.render(text, True, (0, 0, 0))
        self.button_image = pygame.Surface((w, h))
        self.button_image.fill((96, 96, 96))
        self.button_image.blit(text_surf, text_surf.get_rect(center = (w // 2, h // 2)))
        self.hover_image = pygame.Surface((w, h))
        self.hover_image.fill((96, 96, 96))
        self.hover_image.blit(text_surf, text_surf.get_rect(center = (w // 2, h // 2)))
        pygame.draw.rect(self.hover_image, (96, 196, 96), self.hover_image.get_rect(), 3)
        self.clicked_image = pygame.Surface((w, h))
        self.clicked_image.fill((96, 196, 96))
        self.clicked_image.blit(text_surf, text_surf.get_rect(center = (w // 2, h // 2)))
        self.image = self.button_image
        self.rect = pygame.Rect(x, y, w, h)
        self.clicked = False
        self.buttons = None

    def setRadioButtons(self, buttons):
        self.buttons = buttons

    def update(self, event_list):
        hover = self.rect.collidepoint(pygame.mouse.get_pos())
        for event in event_list:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if hover and event.button == 1:
                    for rb in self.buttons:
                        rb.clicked = False
                    self.clicked = True
        
        self.image = self.button_image
        if self.clicked:
            self.image = self.clicked_image
        elif hover:
            self.image = self.hover_image


pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
font50 = pygame.font.SysFont(None, 50)

radioButtons = [
    RadioButton(50, 40, 200, 60, font50, "option 1"),
    RadioButton(50, 120, 200, 60, font50, "option 2"),
    RadioButton(50, 200, 200, 60, font50, "option 3")
]
for rb in radioButtons:
    rb.setRadioButtons(radioButtons)
radioButtons[0].clicked = True

group = pygame.sprite.Group(radioButtons)

run = True
while run:
    clock.tick(60)
    event_list = pygame.event.get()
    for event in event_list:
        if event.type == pygame.QUIT:
            run = False 

    group.update(event_list)

    window.fill(0)
    group.draw(window)
    pygame.display.flip()

pygame.quit()
exit()
GameDev Nov 29 2020 at 18:15
your_button_rect = pygame.Rect(x,y,width,height)
color = (0,0,0)
pos = pygame.mouse.get_pos()
def change_button_color():
    if your_button_rect.colliderect(pos):
        if event.type == pygame.MOUSEBUTTONDOWN: #checks if mouse button is pressed down while the cursor is on the rectangle
            color = (your_desired_Color_RGBvalue)

while True:
    pygame.draw.rect(screen,color,your_button_rect)
    change_button_color()