[PyGame] Button class still not working? - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Game Development (https://python-forum.io/forum-11.html) +--- Thread: [PyGame] Button class still not working? (/thread-15403.html) |
Button class still not working? - mzmingle - Jan-16-2019 Hi - me again haha, I sorted out my button class somewhat, so it now works to an extent. However, I now have the issue that whenever I click one button, it seems to run the function for both buttons on the screen. Does anyone know how to fix this (but I have a limited understanding of Python so... not too complicated if possible lol!) Thank you! class Button: def __init__(self, rect, command, **kwargs): self.processOptions(kwargs) self.rect = pygame.Rect(rect) self.image = pygame.Surface(self.rect.size).convert() self.function = command self.text = self.font.render(self.text,True,self.fontColour) self.text_rect = self.text.get_rect(center=self.rect.center) def processOptions(self, kwargs): settings = { 'colour' :YELLOW, 'text' :'default', 'font' :pygame.font.SysFont(None, 80), 'fontColour' :BLACK, } for kwarg in kwargs: if kwarg in settings: settings[kwarg] = kwargs[kwarg] else: raise AttributeError("{} has no keyword: {}".format(self.__class__.__name__, kwarg)) self.__dict__.update(settings) def getEvent(self): if event.type == pygame.MOUSEBUTTONDOWN: self.onClick() def onClick(self): self.function() def draw(self, surface): self.image.fill(self.colour) surface.blit(self.image, self.rect) surface.blit(self.text, self.text_rect) def letterButton(): # setting buttons of each letter option & its location on the screen done = False while done == False: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True screen.fill(WHITE) title = lettersTitle.render('What letter does your name begin with?', False, BLACK) screen.blit(title, [0, 0]) def teacherChoice(): loginButton = Button((100, 100, 400, 100), loginScreen, text = 'Login') signupButton = Button((100, 250, 400, 100), signupScreen, text = 'New Teacher', colour = BLUE) done = False while done == False: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True screen.fill(WHITE) loginButton.getEvent() signupButton.getEvent() teacherChoice = True signup = False login = False screen.fill(WHITE) loginButton.draw(screen) signupButton.draw(screen) pygame.display.update() if login: teacherChoice = False loginScreen() if signup: teacherChoice = False signupScreen() pygame.quit() studentButton = Button((100, 100, 400, 100), letterButton, text = 'Student') teacherButton = Button((100, 250, 400, 100), teacherChoice, colour = BLUE, text = 'Teacher') while done == False: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True studentButton.getEvent() teacherButton.getEvent() originalScreen = True #screen.fill(WHITE) screen.blit(loginMessage, [100, 10]) mouse = pygame.mouse.get_pos() studentButton.draw(screen) teacherButton.draw(screen) pygame.display.update() pygame.quit() RE: Button class still not working? - metulburr - Jan-16-2019 You shouldnt have two main game loops like that. Here is an example using buttons between states. Notice there is only one while loop in the entire code regardless of the number of states. Classes are a fundamental part of python. I would learn that before trying to program games to be honest. You are not using the button's event check correctly. It needs to be within the main loop's event check. from this: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True studentButton.getEvent() teacherButton.getEvent()to this: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True studentButton.getEvent() teacherButton.getEvent() RE: Button class still not working? - Windspar - Jan-16-2019 1. Do you need to use pygame ? Other gui like tkinter, gtk, wxpython, pyqt, and etc. Has all this built in. Example pygame. import pygame pygame.init() class SimpleButton: def __init__(self, text, rect, callback, font = pygame.font.Font(None, 24), font_color="black", color="dodgerblue", hover_color="lawngreen"): self.text = text self.callback = callback self.font = font if isinstance(rect, pygame.Rect): self.rect = rect else: self.rect = pygame.Rect(rect) if isinstance(font_color, str): self.font_color = pygame.Color(font_color) else: self.font_color = font_color if isinstance(color, str): self.color = pygame.Color(color) else: self.color = color if isinstance(hover_color, str): self.hover_color = pygame.Color(hover_color) else: self.hover_color = hover_color self.hover = False self.render() def draw(self, surface): if self.hover: surface.fill(self.hover_color, self.rect) else: surface.fill(self.color, self.rect) surface.blit(self.image, self.position) def mouse_motion(self, event): self.hover = self.rect.collidepoint(event.pos) def mouse_button_up(self, event): if self.rect.collidepoint(event.pos): if self.callback: self.callback() def render(self): self.image = self.font.render(self.text, 1, self.font_color) self.position = self.image.get_rect() self.position.center = self.rect.center class State: def __init__(self, engine): self.engine = engine def on_draw(self, surface): pass def on_event(self, event): pass class SimpleStateMachine: def __init__(self): # basic pygame setup pygame.display.set_caption('Button & State Example') self.rect = pygame.Rect(0, 0, 800, 600) self.surface = pygame.display.set_mode(self.rect.size) self.clock = pygame.time.Clock() self.state = None # main loop def loop(self): self.running = True while self.running: for event in pygame.event.get(): if event.type == pygame.QUIT: self.running = False if self.state: self.state.on_event(event) if self.state: self.state.on_draw(self.surface) pygame.display.flip() self.clock.tick(30) class FirstState(State): def __init__(self, engine): State.__init__(self, engine) self.buttons = [ SimpleButton('Student', (100, 100, 400, 40), self.button_student), SimpleButton('Teacher', (100, 150, 400, 40), self.button_teacher) ] def button_student(self): self.engine.state = StudentState(self.engine) def button_teacher(self): self.engine.state = TeacherState(self.engine) def on_draw(self, surface): surface.fill(pygame.Color('white')) for button in self.buttons: button.draw(surface) def on_event(self, event): if event.type == pygame.MOUSEBUTTONUP: for button in self.buttons: button.mouse_button_up(event) elif event.type == pygame.MOUSEMOTION: for button in self.buttons: button.mouse_motion(event) class StudentState(State): def __init__(self, engine): State.__init__(self, engine) self.buttons = [ SimpleButton('Back', (100, 100, 400, 40), self.button_back) ] def button_back(self): self.engine.state = FirstState(self.engine) def on_draw(self, surface): surface.fill(pygame.Color('white')) for button in self.buttons: button.draw(surface) def on_event(self, event): if event.type == pygame.MOUSEBUTTONUP: for button in self.buttons: button.mouse_button_up(event) elif event.type == pygame.MOUSEMOTION: for button in self.buttons: button.mouse_motion(event) class TeacherState(State): def __init__(self, engine): State.__init__(self, engine) self.buttons = [ SimpleButton('Login', (100, 100, 400, 40), self.button_login), SimpleButton('New Teacher', (100, 150, 400, 40), self.button_teacher), SimpleButton('Back', (100, 200, 400, 40), self.button_back), ] def button_login(self): print('login') def button_teacher(self): print('teacher') def button_back(self): self.engine.state = FirstState(self.engine) def on_draw(self, surface): surface.fill(pygame.Color('white')) for button in self.buttons: button.draw(surface) def on_event(self, event): if event.type == pygame.MOUSEBUTTONUP: for button in self.buttons: button.mouse_button_up(event) elif event.type == pygame.MOUSEMOTION: for button in self.buttons: button.mouse_motion(event) def main(): engine = SimpleStateMachine() engine.state = FirstState(engine) engine.loop() pygame.quit() if __name__ == '__main__': main()Example. Poor quality tkinter code. import tkinter as tk class App: def __init__(self): self.root = tk.Tk() self.frame = tk.Frame(self.root) self.frame.pack(side='top', fill='both', expand=True) self.frame.grid_rowconfigure(0, weight=1) self.frame.grid_columnconfigure(0, weight=1) self.frames = {} for page in (StartPage, TeacherPage): page_name = page.__name__ frame = page(self.frame, self) self.frames[page_name] = frame frame.frame.grid(row=0, column=0, sticky='nsew') self.show_frame('StartPage') self.root.mainloop() def show_frame(self, page_name): self.frames[page_name].frame.tkraise() class StartPage: def __init__(self, parent, controller): self.controller = controller self.frame = tk.Frame(parent) self.student = tk.Button(self.frame, text='Student') self.student.pack() self.teacher = tk.Button(self.frame, text='Teacher') self.teacher.bind("<Button-1>", self.call_teacher) self.teacher.pack() def call_teacher(self, event): self.controller.show_frame('TeacherPage') class TeacherPage: def __init__(self, parent, controller): self.controller = controller self.frame = tk.Frame(parent) self.login = tk.Button(self.frame, text='Login') self.login.pack() self.new_teacher = tk.Button(self.frame, text="New Teacher") self.new_teacher.pack() App() RE: Button class still not working? - metulburr - Jan-16-2019 (Jan-16-2019, 04:10 PM)Windspar Wrote: . Do you need to use pygame ?@OP yeah if your just making buttons then your better off just using a GUI. If you are eventually turning this into a game, or just pygame learning, then its fine. |