#!/usr/bin/env python3 from abc import abstractmethod from typing import Tuple, Callable import pygame class IBoard: @abstractmethod def draw(self, screen: pygame.Surface): raise NotImplementedError() @abstractmethod def handle_event(self, event: pygame.event.Event): raise NotImplementedError() class Button: def __init__(self, position: pygame.Rect, cbk: Callable[[], None]): self.position: pygame.Rect self.set_position(position) self.cbk = cbk def set_position(self, position: pygame.Rect): self.position = position def draw(self, screen: pygame.Surface): pygame.draw.rect(screen, "black", self.position, 0) def pos_is_inside(self, pos: Tuple) -> bool: return (self.position.left < pos[0] and (self.position.left + self.position.width) > pos[0]) and \ (self.position.top < pos[1] and (self.position.top + self.position.height) > pos[1]) def handle_event(self, event: pygame.event.Event): if event.type == pygame.MOUSEBUTTONUP: if event.button == 1 and self.pos_is_inside(event.pos): self.cbk() class MenuBoard(IBoard): def __init__(self): self.buttons = [Button(pygame.Rect(10, 10, 30, 30), lambda: print("siema")), Button(pygame.Rect(50, 10, 30, 30), lambda: print("elo"))] def handle_event(self, event: pygame.event.Event): for b in self.buttons: b.handle_event(event) def draw(self, screen: pygame.Surface): screen.fill("purple") for b in self.buttons: b.draw(screen) class App: def __init__(self): pygame.init() info = pygame.display.Info() self.screen = pygame.display.set_mode((info.current_w, info.current_h), flags=pygame.FULLSCREEN) self.clock = pygame.time.Clock() self.running = False self.board: IBoard = MenuBoard() def loop(self): self.running = True while self.running: # poll for events # pygame.QUIT event means the user clicked X to close your window for event in pygame.event.get(): if event.type == pygame.QUIT: self.running = False self.board.handle_event(event) self.board.draw(self.screen) pygame.display.flip() self.clock.tick(30) pygame.quit() if __name__ == '__main__': app = App() app.loop()