The button does not become the color I need

Question:

I have a button that changes color when the cursor hovers over it, and I want to make it so that when the button is pressed, it leaves the color that it has when the cursor hovers over it. There are my unsuccessful attempts to do this in the code. I think I made a mistake somewhere in the "draw" function in the "Button" class.

import pygame
import pygame_widgets as pw

pygame.init()  # Инициализируем модуль pygame

width = 1134 # ширина игрового окна
height = 693  # высота игрового окна
fps = 30  # частота кадров в секунду
game_name = "Тренажёр"  # название нашей игры

snd_dir = 'sound/'  # Путь до папки со звуками
img_dir = 'images/'  # Путь до папки со спрайтами

# Цвета
BLACK = "#000000"
WHITE = "#FFFFFF"
RED = "#FF0000"
GREEN = "#008000"
BLUE = "#0000FF"
CYAN = "#00FFFF"

OneNumber = list(range(1, 10))
TwoNumber = list(range(10, 100))
ThreeNumber = list(range(100, 1000))

button_sound = pygame.mixer.Sound(snd_dir + 'button.mp3')


class Background(pygame.sprite.Sprite):
    def __init__(self, image_file, location):
        pygame.sprite.Sprite.__init__(self)  #call Sprite initializer
        self.image = pygame.image.load(image_file)
        self.rect = self.image.get_rect()
        self.rect.left, self.rect.top = location


def print_text(message, x, y, font_color=(0, 0, 0), font_type='ttf/Ping Pong.ttf', font_size=30):
    font_type = pygame.font.Font(font_type, font_size)
    text = font_type.render(message, True, font_color)
    screen.blit(text, (x, y))


class Button:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.inactive_color = (255, 165, 0)
        self.active_color = (13, 162, 58)
        self.button_active = False

    def draw(self,x ,y, message, action=None):
        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()

        if x < mouse[0] < x + self.width:
            if y < mouse[1] < y + self.height:
                pygame.draw.rect(screen, self.active_color, (x, y, self.width, self.height))

                if click[0] == 1:
                    pygame.mixer.Sound.play(button_sound)
                    pygame.draw.rect(screen, self.active_color, (x, y, self.width, self.height))
                    self.button_active = True
                    pygame.time.delay(300)
                    print(self.button_active)



                    #if action is not None:
                        #action()

            elif y < mouse[1] < y + self.height and self.button_active == True:
                pygame.draw.rect(screen, self.active_color, (x, y, self.width, self.height))

        elif x > mouse[0] > x + self.width and self.button_active == False:
            pygame.draw.rect(screen, self.inactive_color, (x,y, self.width, self.height))

        print_text(message, x + 10, y + 10)


BackGround = Background(img_dir + "fon.jpg", [0,0])

# Создаем игровой экран
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption(game_name)  # Заголовок окна
icon = pygame.image.load(img_dir + 'icon.png')  # загружаем файл с иконкой
pygame.display.set_icon(icon)  # устанавливаем иконку в окно

timer = pygame.time.Clock()  # Создаем таймер pygame
run = True


button = Button(90, 50)


while run:  # Начинаем бесконечный цикл
    timer.tick(fps)  # Контроль времени (обновление игры)
    for event in pygame.event.get():  # Обработка ввода (события)
        if event.type == pygame.QUIT:  # Проверить закрытие окна
            run = False  # Завершаем игровой цикл
    # Рендеринг (прорисовка)

    screen.fill(WHITE)  # Заливка заднего фона
    screen.blit(BackGround.image, BackGround.rect)

    button.draw(20, 100, "wow")

    pygame.display.update()  # Переворачиваем экран
pygame.quit()  # Корректно завершаем игру
Asked By: Neytron

||

Answers:

Test if the mouse is on the button:

button_rect = pygame.Rect(x, y, self.width, self.height)
mouse_on_button = button_rect.collidepoint(mouse)

Set self.button_active when the mouse is on the button and the mouse button is pressed:

if mouse_on_button and click[0] == 1:
    self.button_active = True

Set the color depending on mouse_on_button and self.button_active:

color = self.inactive_color
if mouse_on_button or self.button_active:
    color = self.active_color 
pygame.draw.rect(screen, color, button_rect)

class Button:

class Button:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.inactive_color = (255, 165, 0)
        self.active_color = (13, 162, 58)
        self.button_active = False
        
    def draw(self,x ,y, message, action=None):
        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()

        button_rect = pygame.Rect(x, y, self.width, self.height)
        mouse_on_button = button_rect.collidepoint(mouse)
        if mouse_on_button and click[0] == 1:
            self.button_active = True

        color = self.inactive_color
        if mouse_on_button or self.button_active:
            color = self.active_color 
            
        pygame.draw.rect(screen, color, button_rect)
        print_text(message, x + 10, y + 10)

However pygame.mouse.get_pressed() is not an event. If you want to toggle the button on and off you have to use the MOUSEBUTTONDOWN event. pygame.mouse.get_pressed() returns a list of Boolean values ​​that represent the state (True or False) of all mouse buttons. The state of a button is True as long as a button is held down. The MOUSEBUTTONDOWN event occurs once when you click the mouse button and the MOUSEBUTTONUP event occurs once when the mouse button is released.

class Button:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.inactive_color = (255, 165, 0)
        self.active_color = (13, 162, 58)
        self.button_active = False
        
    def draw(self,x ,y, message, clicked, action=None):
        mouse = pygame.mouse.get_pos()
        
        button_rect = pygame.Rect(x, y, self.width, self.height)
        mouse_on_button = button_rect.collidepoint(mouse)
        if mouse_on_button and clicked:
            self.button_active = not self.button_active

        color = self.inactive_color
        if mouse_on_button or self.button_active:
            color = self.active_color 
            
        pygame.draw.rect(screen, color, button_rect)
        print_text(message, x + 10, y + 10)
while run:
    timer.tick(fps) 
    left_click = False
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            left_click = event.button = 1


    screen.fill(WHITE) 
    screen.blit(BackGround, (0, 0))

    button.draw(20, 100, "wow", left_click)

    pygame.display.update() 

Also see Pygame mouse clicking detection.

Answered By: Rabbid76
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.