Skip to content
Advertisement

Pygame: How to display a new box when user clicks an area, and close the box when the user clicks again

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:

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement