I am new to python and pygame and I am developing a weather app as a project to learn both.
I want to display a new rectangle when a user is clicking an area (=button) of the screen. The new rectangle should be visible until the user clicks again, this time anywhere on the screen.
I have my main loop where the screen is drawn, and then checking for event MOUSEBUTTONUP
and with collidepoint
checking if the mouse was on the button and then updating variable newscreen
to True
Then I have a new loop that should be running until the user is clicking again, anywhere on the screen. The problem is that the new while loop is breaking as soon as the mouse is moved. It also looks like the first condition, checking if the user is clicking the button, is returning true in every iteration until the mouse is moved. Why is this not only returning true one time?
Can this be done without having a second while loop?
import pygame import pygame.freetype from pygame.locals import * pygame.init() SIZE = 500, 200 RED = (75, 0, 0) NOTGREY = (75, 150, 150) #set up the screen screen = pygame.display.set_mode([800, 480]) # create rectangle #Rect(position from left, position from top, width in pixels, height in pixels) rect = Rect(50, 20, 200, 80) rect2 = Rect(50,200, 200, 300) running = True newscreen = False while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() running = False screen.fill(NOTGREY) pygame.draw.rect(screen, RED, rect) # If user is clicking (on release of click) on the rectangle area update newscreen to true if event.type == pygame.MOUSEBUTTONUP: if event.button == 1: # Left mouse button. if rect.collidepoint(event.pos): newscreen = True print("Clicking area") while newscreen == True: pygame.draw.rect(screen, RED, rect2) pygame.display.flip() if event.type == pygame.MOUSEBUTTONUP: if event.button == 1: # Left mouse button. print("now you clicked again") newscreen = False pygame.display.flip()
Advertisement
Answer
You have to draw the rectangles depending on the state of newscreen
:
if newscreen: pygame.draw.rect(screen, RED, rect2) else: pygame.draw.rect(screen, RED, rect)
All the events need to be handled in one event loop. Toggle the state of newscreen
when the button is clicked (newscreen = not newscreen
):
if event.type == pygame.MOUSEBUTTONUP: if event.button == 1: # Left mouse button. if newscreen or rect.collidepoint(event.pos): newscreen = not newscreen
Complete example:
import pygame import pygame.freetype from pygame.locals import * pygame.init() SIZE = 500, 200 RED = (75, 0, 0) NOTGREY = (75, 150, 150) #set up the screen screen = pygame.display.set_mode([800, 480]) # create rectangle #Rect(position from left, position from top, width in pixels, height in pixels) rect = Rect(50, 20, 200, 80) rect2 = Rect(50,200, 200, 300) running = True newscreen = False while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() running = False if event.type == pygame.MOUSEBUTTONUP: if event.button == 1: # Left mouse button. if newscreen or rect.collidepoint(event.pos): newscreen = not newscreen screen.fill(NOTGREY) if newscreen: pygame.draw.rect(screen, RED, rect2) else: pygame.draw.rect(screen, RED, rect) pygame.display.flip()
The typical PyGame application loop has to:
- limit the frames per second to limit CPU usage with
pygame.time.Clock.tick
- handle the events by calling either
pygame.event.pump()
orpygame.event.get()
. - update the game states and positions of objects dependent on the input events and time (respectively frames)
- clear the entire display or draw the background
- draw the entire scene (
blit
all the objects) - update the display by calling either
pygame.display.update()
orpygame.display.flip()