How to make Buttons in Pygame

Another update of the code to make buttons with pygame. This is better beacause it makes you add more easily buttons, changing the dimention when you put a feedback to the click, like changing the text.

import pygame
 
pygame.init()
screen = pygame.display.set_mode((500, 600))
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 20)
 
 
class Button:
    """Create a button, then blit the surface in the while loop"""
 
    def __init__(self, text,  pos, font, bg="black", feedback=""):
        self.x, self.y = pos
        self.font = pygame.font.SysFont("Arial", font)
        if feedback == "":
            self.feedback = "text"
        else:
            self.feedback = feedback
        self.text = self.change_text(text, bg)
 
    def change_text(self, text="Clicked", bg="black"):
        """Change the text whe you click"""
        try:
            # print(self.text)
            self.text = self.font.render(text, 1, pygame.Color("White"))
            self.size2 = self.text.get_size()
            if self.size2 < self.size:
                self.surface = pygame.Surface(self.size)
                self.surface.fill(self.bg)
            else:
                self.surface = pygame.Surface(self.size2)
                self.surface.fill(self.bg)

            self.surface.blit(self.text, (0, 0))
            self.rect = pygame.Rect(self.x, self.y, self.size[0], self.size[1])
        except AttributeError:
            self.bg = bg
            self.text = self.font.render(text, 1, pygame.Color("White"))
            print(self.text)
            print("hello")
            self.size = self.text.get_size()
            print(self.size)
            self.surface = pygame.Surface(self.size)
            self.surface.fill(bg)
            self.surface.blit(self.text, (0, 0))
            self.rect = pygame.Rect(self.x, self.y, self.size[0], self.size[1])

 
    def pack(self):
        screen.blit(self.surface, (self.x, self.y))
 
    def clicked(self):
        """ Returns 1 if you click on the button """

    def mouse_click(self, event):
        """ checks if you click the mouse button and then if it's on the button """
        if event.type == pygame.MOUSEBUTTONDOWN:
            if pygame.mouse.get_pressed()[0]:
                print(self)
                if self.clicked():
                    return 1
                    pass
        return 0


    def clicked(self):
        """ checks if the moouse is on the button """

        x, y = pygame.mouse.get_pos()
        if self.rect.collidepoint(x, y):
            return 1
            pass
        return 0
 
 
def mainloop():
    """ The infinite loop where things happen """
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
            if button1.mouse_click(event):
                button1.change_text()
        button1.pack()
        clock.tick(30)
        pygame.display.update()
 
'''
To create a button

b = Button(
    "text",    # string
    (100, 100) # coordinates
    font=30,
    bg='green',
    feedback="Clicked" # text changes to this when clicked
    )

''' 

if __name__ == '__main__':
    button1 = Button(
        "Click here",
        (100, 100),
        font=30,
        bg="navy",
        feedback="You clicked me")
    mainloop()

To use this class:

  • import like: from buttons import *
  • create a button like you see in the end of the code
  • check the click of the mouse on the button with button1.mouse_click(event) like you see in the mainloop
  • add an action like button1.change_text()
  • show the button with button1.pack() like in the mainloop

Example of use of buttons into another script

import pygame
import sys
from buttons import *

# ============= GLOBALS ======================
pygame.init()
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
font = pygame.font.SysFont
font1 = font("Arial", 24)

class Sprite(pygame.sprite.Sprite):
    def __init__(self, image):
        super().__init__()
        self.image = pygame.transform.scale(
            pygame.image.load(image), (256, 256))


player = Sprite("imgs/player/idle (1).png")
text_player = font1.render("Player", 1, (255, 255, 255))

def show_time():
    screen.blit(player.image, (10, 10))
    screen.blit(text_player, (50, 256))
    b1.pack()


def init():
    """ Get the user intention to quit the game """
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            print("\nExit from pygame\n\n")
            sys.exit()
        if b1.mouse_click(event):
            b1.change_text("You clicked me")
    show_time()
    clock.tick(60)
    pygame.display.update()


def gameloop():
    """ The main loop to run the game """
    while True:
        init()

b1 = Button(
    "click me",
    (200, 200),
    font=30,
    bg="red",
    feedback="There you go"
    )


gameloop()
A button in a game

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

A more stylish button in pygame

This is cool. Look at this code

I used in my new version of flap.py
def button(screen, position, text):
    font = pygame.font.SysFont("Arial", 50)
    text_render = font.render(text, 1, (255, 0, 0))
    x, y, w , h = text_render.get_rect()
    x, y = position
    pygame.draw.line(screen, (150, 150, 150), (x, y), (x + w , y), 5)
    pygame.draw.line(screen, (150, 150, 150), (x, y - 2), (x, y + h), 5)
    pygame.draw.line(screen, (50, 50, 50), (x, y + h), (x + w , y + h), 5)
    pygame.draw.line(screen, (50, 50, 50), (x + w , y+h), [x + w , y], 5)
    pygame.draw.rect(screen, (100, 100, 100), (x, y, w , h))
    return screen.blit(text_render, (x, y))

You can do like this

    b1 = button(screen, (600, 500), "Quit")
    b2 = button(screen, (500, 500), "Start")

And make some user interaction like this

def menu():
“”” This is the menu that waits you to click the s key to start “””

b1, b2 = splash_page()
while True:
    for event in pygame.event.get():
        if (event.type == pygame.QUIT):
            exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                exit()
            if event.key == pygame.K_s:
                start()
        if event.type == pygame.MOUSEBUTTONDOWN:
            if b1.collidepoint(pygame.mouse.get_pos()):
                exit()
            elif b2.collidepoint(pygame.mouse.get_pos()):
                start()
    pygame.display.update()
pygame.quit()

Something simpler

import pygame

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

def button(screen, position, text):
    font = pygame.font.SysFont("Arial", 50)
    text_render = font.render(text, 1, (255, 0, 0))
    x, y, w , h = text_render.get_rect()
    x, y = position
    pygame.draw.line(screen, (150, 150, 150), (x, y), (x + w , y), 5)
    pygame.draw.line(screen, (150, 150, 150), (x, y - 2), (x, y + h), 5)
    pygame.draw.line(screen, (50, 50, 50), (x, y + h), (x + w , y + h), 5)
    pygame.draw.line(screen, (50, 50, 50), (x + w , y+h), [x + w , y], 5)
    pygame.draw.rect(screen, (100, 100, 100), (x, y, w , h))
    return screen.blit(text_render, (x, y))

def start():
    print("Ok, let's go")

def menu():
    """ This is the menu that waits you to click the s key to start """
    b1 = button(screen, (400, 300), "Quit")
    b2 = button(screen, (500, 300), "Start")
    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()
                key_to_start = event.key == pygame.K_s or event.key == pygame.K_RIGHT or event.key == pygame.K_UP
                if key_to_start:
                    start()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if b1.collidepoint(pygame.mouse.get_pos()):
                    pygame.quit()
                elif b2.collidepoint(pygame.mouse.get_pos()):
                    start()
        pygame.display.update()
    pygame.quit()

menu()

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.