sebsee
sebsee

Reputation: 83

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()

Upvotes: 1

Views: 495

Answers (3)

sebsee
sebsee

Reputation: 83

Solved with adding all events into one event loop as mentioned above. I still wanted the second box to be closed when clicking anywher on the screen. Solved by adding another event check, for MOUSEBUTTONDOWN. It did not work to have another MOUSEBUTTONUP event.

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 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")
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # Left mouse button.
                newscreen = False
                print("now you clicked again")

    screen.fill(NOTGREY)
    pygame.draw.rect(screen, RED, rect)

    if newscreen:
        pygame.draw.rect(screen, RED, rect2)

    pygame.display.flip()

Upvotes: 0

Heang Sok
Heang Sok

Reputation: 140

I might not use the second while loop:

 while running:
        # keep loop running at the right speed
        clock.tick(30) // Frame per second
        screen.fill(BLACK) // never forget this line of code, especially when you work with animation
        pos = pygame.mouse.get_pos()
        # Process input (events)
        for event in pygame.event.get():
            # check for closing window
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                click = True

            if click:
                show_new_screen()
                click = False

Upvotes: 0

Rabbid76
Rabbid76

Reputation: 210909

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:

Upvotes: 2

Related Questions