How to make a button in Pygame updated to 26.8.2021

Recap: doing code for buttons in pygame.

Today I added a new style and a way to customize also the hovering colors of the button that now can be different for each one or be left as it is by default.

screen

Video:

Code:

import pygame
import pygame.gfxdraw


pygame.init()
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()

buttons = pygame.sprite.Group()

class Button(pygame.sprite.Sprite):
    def __init__(self, screen, position, text, size,
        colors="white on blue",
        hover_colors="red on green",
        style=1, borderc=(255,255,255)):
        # the hover_colors attribute needs to be fixed
        super().__init__()
        self.text = text
        # --- colors ---
        self.colors = colors
        self.original_colors = colors
        self.hover_colors = hover_colors
        self.fg, self.bg = self.colors.split(" on ")
        self.style = style
        self.borderc = borderc # for the style2
        # font
        self.font = pygame.font.SysFont("Arial", size)
        self.render()
        self.x, self.y, self.w , self.h = self.text_render.get_rect()
        self.x, self.y = position
        self.rect = pygame.Rect(self.x, self.y, self.w, self.h)
        self.position = position
        self.pressed = 1
        buttons.add(self)

    def render(self):
        self.text_render = self.font.render(self.text, 1, self.fg)
        self.image = self.text_render

    def update(self):
        self.fg, self.bg = self.colors.split(" on ")
        if self.style == 1:
            self.draw_button1()
        elif self.style == 2:
            self.draw_button2()
        self.hover()
        self.click()

    def draw_button1(self):
        ''' draws 4 lines around the button and the background '''
        # horizontal up
        pygame.draw.line(screen, (150, 150, 150), (self.x, self.y), (self.x + self.w , self.y), 5)
        pygame.draw.line(screen, (150, 150, 150), (self.x, self.y - 2), (self.x, self.y + self.h), 5)
        # horizontal down
        pygame.draw.line(screen, (50, 50, 50), (self.x, self.y + self.h), (self.x + self.w , self.y + self.h), 5)
        pygame.draw.line(screen, (50, 50, 50), (self.x + self.w , self.y + self.h), [self.x + self.w , self.y], 5)
        # background of the button
        pygame.draw.rect(screen, self.bg, (self.x, self.y, self.w , self.h))  

    def draw_button2(self):
        ''' a linear border '''
        pygame.draw.rect(screen, self.bg, (self.x, self.y, self.w , self.h))
        pygame.gfxdraw.rectangle(screen, (self.x, self.y, self.w , self.h), self.borderc)

    def hover(self):
        ''' checks if the mouse is over the button and changes the color if it is true '''
        if self.rect.collidepoint(pygame.mouse.get_pos()):
            # you can change the colors when the pointer is on the button if you want
            self.colors = self.hover_colors
        else:
            self.colors = self.original_colors
        self.render()

    def click(self):
        ''' checks if you click on the button and makes the call to the action just one time'''
        if self.rect.collidepoint(pygame.mouse.get_pos()):
            if pygame.mouse.get_pressed()[0] and self.pressed == 1:
                print(self.position)
                print(self.colors)
                print(self.hover_colors)
                print(self.fg)
                print(self.bg)
                self.pressed = 0
            if pygame.mouse.get_pressed() == (0,0,0):
                self.pressed = 1


def loop():
    while True:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT):
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()

        buttons.update()
        buttons.draw(screen)
        clock.tick(60)
        pygame.display.update()
    pygame.quit()
# BUTTONS ISTANCES
b0 = Button(screen, (10, 10), "1st button", 55, "black on white")
b1 = Button(screen, (10, 100), "2nd button", 40, "black on red")
b2 = Button(screen, (10, 170), "3rd button", 36, "red on yellow", hover_colors="white on red", style=2, borderc=(255,255,0))
print(b0.x)

loop()

Repository: https://github.com/formazione/pygame_button

Let’s make button.py as a module

Let’s make button.py as a module

Now I want to put the buttons code outside of the main function to stay more organized

import pygame

pygame.init()
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()

buttons = pygame.sprite.Group()

class Button(pygame.sprite.Sprite):
    def __init__(self, screen, position, text, size,
        colors="white on blue",
        hover_colors="red on green"):
        # the hover_colors attribute needs to be fixed
        super().__init__()
        self.text = text
        self.colors = colors
        self.original_colors = colors
        self.hover_colors = hover_colors
        self.fg, self.bg = self.colors.split(" on ")
        self.font = pygame.font.SysFont("Arial", size)
        self.text_render = self.font.render(self.text, 1, self.fg)
        self.image = self.text_render
        self.x, self.y, self.w , self.h = self.text_render.get_rect()
        self.x, self.y = position
        self.rect = pygame.Rect(self.x, self.y, self.w, self.h)
        self.position = position
        self.pressed = 1
        buttons.add(self)

    def update(self):
        self.fg, self.bg = self.colors.split(" on ")
        self.draw_button()
        self.hover()
        self.click()

    def draw_button(self):
        ''' draws 4 lines around the button and the background '''
        pygame.draw.line(screen, (150, 150, 150), (self.x, self.y), (self.x + self.w , self.y), 5)
        pygame.draw.line(screen, (150, 150, 150), (self.x, self.y - 2), (self.x, self.y + self.h), 5)
        pygame.draw.line(screen, (50, 50, 50), (self.x, self.y + self.h), (self.x + self.w , self.y + self.h), 5)
        pygame.draw.line(screen, (50, 50, 50), (self.x + self.w , self.y + self.h), [self.x + self.w , self.y], 5)
        pygame.draw.rect(screen, self.bg, (self.x, self.y, self.w , self.h))

    def hover(self):
        ''' checks if the mouse is over the button and changes the color if it is true '''
        if self.rect.collidepoint(pygame.mouse.get_pos()):
            self.colors = self.hover_colors
        else:
            self.colors = self.original_colors

    def click(self):
        ''' checks if you click on the button and makes the call to the action just one time'''
        if self.rect.collidepoint(pygame.mouse.get_pos()):
            if pygame.mouse.get_pressed()[0] and self.pressed == 1:
                print(self.position)
                self.pressed = 0
            if pygame.mouse.get_pressed() == (0,0,0):
                self.pressed = 1


def loop():
    while True:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT):
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()

        buttons.update()
        buttons.draw(screen)
        clock.tick(60)
        pygame.display.update()
    pygame.quit()
# BUTTONS ISTANCES
b0 = Button(screen, (10, 10), "1st button", 55, "black on white")
b1 = Button(screen, (10, 100), "2nd button", 40, "black on red")
b2 = Button(screen, (10, 200), "3rd button", 36, "red on yellow")
print(b0.x)

loop()

I will import this module in the main function that now looks like this

import pygame
import pygame.gfxdraw
from buttons import *

pygame.init()


def loop():
    while True:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT):
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()

        buttons.update()
        buttons.draw(screen)
        clock.tick(60)
        pygame.display.update()
    pygame.quit()

# BUTTONS ISTANCES
b0 = Button((10, 10), "Click", 55, "black on white")
b1 = Button((10, 100), "Run", 40, "black on red")

b2 = Button((10, 170), "Save", 36, "red on yellow",
    hover_colors="blue on orange", style=2, borderc=(255,255,0))

loop()

Here we find the three istances of the button.

In the next post we will see new features like:

  • adding a command
  • change the cursor when hover

See ya soon then.

Repo: https://github.com/formazione/pygame_button.git


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.