Entrada destacada

Como usar enums en Android, kotlin

Creando botones en Python usando pygame

Existen distintas librerías de python para implementar interfaces gráficas y que puedan usarse junto a pygame, pero también podemos crear nuestros componentes GUI (graphical user interface) si estos no requieren de mucha complejidad usando alguna librería de dibujo de gráficos como pygame.

Si bien pygame no tiene incorporado componentes GUI, soporta la carga de imágenes y la gestión de eventos de teclado y ratón los cuales son suficientes para implementar botones Figura 1.

Figura 1: Ejemplo final de implementación de botones 

Implementar botones usando imágenes y eventos de ratón también nos puede servir a modo de práctica de programación.

Base de la aplicación y dibujo de imágenes del botón


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import pygame
import random
from pygame.locals import *

FONDO = (32, 30, 32)
BLANCO = (255, 255, 255)
COLOR_TEXTO = (50, 60, 80)

def dibujar_panel():
    panel = pygame.transform.scale(imagen_panel, [560, 420])
    pantalla.blit(panel, [20, 20])

def dibujar_botones(lista_botones):
    for boton in lista_botones:
        if boton['on_click']:
            pantalla.blit(boton['imagen_pressed'], boton['rect'])
        else:
            pantalla.blit(boton['imagen'], boton['rect'])

def main():
    game_over = False
    click = False
    clock = pygame.time.Clock()
    rect_boton_1 = imagen_boton.get_rect()
    botones = []
    rect_boton_1.topleft = [80, 80]
    botones.append(
        {'texto': "Nuevo número", 'imagen': imagen_boton, 'imagen_pressed': imagen_boton_pressed, 'rect': rect_boton_1,
         'on_click': True})
    while not game_over:
        for event in pygame.event.get():
            if event.type == QUIT:
                game_over = True
        pantalla.fill(FONDO)
        dibujar_panel()
        dibujar_botones(botones)
        pygame.display.flip()
        clock.tick(60)
    pygame.quit()

pygame.init()
dimensiones = [600, 460]
pantalla = pygame.display.set_mode(dimensiones)
pygame.display.set_caption("Entrada de texto")
imagen_panel = pygame.image.load("../img/panel.png")
imagen_boton = pygame.image.load("../img/button.png")
imagen_boton_pressed = pygame.image.load("../img/buttonPressed.png")

if __name__ == '__main__':
    main()

En las líneas 1 a 3 se importan las librerías pygame para los gráficos y random para generar números aleatorios  la manera en que importamos el modulo pygame.locals en la línea 3 nos ayuda a usar por ejemplo QUIT en lugar de pygame.QUIT.

Después definimos algunos colores, en le línea 9 comienza la definición de la función dibujar_panel, que usamos para dibujar la imagen del panel de fondo la cual es escalada a 560x420, ya que la imagen original es cuadrada y necesitamos que se ajuste a las medidas de la pantalla, las imágenes pueden escalarse a cualquier medida pero ten cuidado de no hacer que la imagen se distorsione.

La función dibujar_botones recorre una lista de botones y dibuja la imagen de cada botón, cada botón es un diccionario que almacena sus propiedades, la clave on_click nos indica el estado del botón y así saber que imagen dibujar como se muestra en Figura 2.

Figura 2: Imagen de botón normal y botón presionado

La función main ejecutara el bucle principal de la aplicación en la línea 24 obtenemos el objeto rect de la imagen del botón, el cual nos facilitará la detección de la colisión con el cursor del ratón, botones será la lista que almacenará todos los botones que deseemos agregar a la pantalla antes de agregar un elemento a lista de botones fijamos su posición.

Representaremos cada botón con un diccionario con la siguiente estructura:

  • texto: el texto que se mostrara sobre el botón.
  • imagen: la imagen principal. 
  • imagen_pressed: la imagen del botón presionado.
  • rect: objeto rect del botón, el cual indica la posición y medidas del botón.
  • on_click: almacena el estado del botón, false indica que el botón no está presionado true indica que ha sido pulsado.

Las líneas 30 a 39 definen el bucle principal, código que ya hemos explicado en tutoriales anteriores ya que es una estructura general que debe llevar casi todo programa de pygame.

Finalmente iniciamos pygame y lanzamos la pantalla principal indicando las dimensiones y el título de la ventana, las líneas 45 a 47 cargan los archivos fuente de las imágenes del botón y del panel.

Detectar click sobre el botón

34
35
36
37
38
39
40
            if event.type == MOUSEBUTTONDOWN:
                mouse = event.pos
                for boton in botones:
                    boton['on_click'] = boton['rect'].colliderect([mouse[0], mouse[1], 1, 1])
            if event.type == MOUSEBUTTONUP:
                for boton in botones:
                    boton['on_click'] = False

Si un botón del ratón es pulsado se detecta un evento de tipo MOUSEBUTTONDOWN en la línea 35 obtenemos la posición actual del ratón, después con un bucle for buscamos si las coordenadas del ratón está sobre el área de la imagen uno de los botones (por ahora sólo tenemos un botón en la lista) usando el método colliderect del objeto rect del botón, está función devolverá true o false dependiendo de si existe colisión o no.

Figura 3: Detección de clcik sobre el botón.

Si un botón del ratón es liberado volvemos a recorrer la lista de botones por si el estado de click de un botón está en true pasarlo de nuevo a false.

Dibujar el texto del botón


9
10
11
12
13
14
15
16
def dibujar_texto(texto, contenedor, fuente_render, color):
    text = fuente_render.render(texto, 1, color)
    rect_text = text.get_rect()
    centroX = contenedor.width / 2
    centroY = contenedor.height / 2
    diferencia_x = centroX - rect_text.center[0]
    diferencia_y = centroY - rect_text.center[1]
    pantalla.blit(text, [contenedor.left + diferencia_x, contenedor.top + diferencia_y])

La función dibujar_texto renderiza el texto que queremos que tanga el botón, el primer parámetro es la cadena de texto, el objeto rect del botón contenedor, el tipo de fuente que se va utilizar, y el color del texto.

dibujar_texto(boton['texto'], boton['rect'], fuente, BLANCO)

Llamamos la función al final de la función dibujar_botones fuera del if, el objeto fuente lo podemos definir casi al final de todos el código después de cargar la imagenes pero antes de ejecutar la función main.

fuente = pygame.font.SysFont('Courier', 20)
fuente_numero = pygame.font.SysFont('Pacifico Regular', 30)

El nombre de la fuente puede ser cualquiera que se tenga instalada en el sistema y también se le define el tamaño de texto.

Código fuente de ejemplo de uso de botones


Button.py

El ejemplo final es una aplicación (ver Figura 1) en la cual se generan números aleatorios y se muestran por un instante, el usuario debe recordar ese número y escribirlo pulsando sobre los botones con números finalmente al escribir los 4 dígitos se comprueba si se ha introducido el número correcto.

Comenta tus dudas en la sección de comentarios.


Comentarios