简体   繁体   中英

How to detect mouse clicks inside nested buttons in pygame

I'm trying to create a GUI that displays some buttons when you click a button. However, I cannot figure out how to detect if you click the nested button. Here's my code:

import pygame
from pygame.locals import *

import sys
import os
import time
from random import randrange, randint
import base64
from configparser import ConfigParser
import tkinter
from tkinter import Tk, messagebox, simpledialog

configure = ConfigParser()
configure.read('dooroperatingsystempassword.txt')
start_time = time.time()

WIDTH = 801
HEIGHT = 452
CENTER_X = WIDTH / 2
CENTER_Y = HEIGHT / 2

admin = False
complete = False
failed = False
loading = False
first_time_password = True
back_button_dofalsetotrue = 'none'
back_button_dotruetofalse = 'none'

start_screen = True
system_screen = False
privacy_screen = False
account_screen = False
time_button_screen = False
keyboard_screen = False
shutdown_screen = False

system = pygame.image.load(r'images\system_button.png')
privacy = pygame.image.load(r'images\security_button.png')
background = pygame.image.load(r'images\background.png')
shutdown = pygame.image.load(r'images\shutdown.png')
doors_icon = pygame.image.load(r'images\doors2_icon.png')


pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((WIDTH, HEIGHT))

pygame.mouse.set_visible(1)
pygame.display.set_caption('Doors Operating System (DOS)')
pygame.display.set_icon(doors_icon)

root = Tk()
root.withdraw()
shutdown_img_for_tkinter = tkinter.PhotoImage(file=r'images\shutdown.png')
root.iconphoto(False, shutdown_img_for_tkinter)

def letters_off():
    global loading
    if loading:
        loading = False

def decode(decode_message):
    base64_bytes = decode_message.encode('ascii').decode('UTF-8')
    message = base64.b64decode(base64_bytes).decode('UTF-8')
    return message

def check_mouse_pos(pos):
    global start_screen, loading_first_time_password
    global system_screen, privacy_screen, account_screen, time_button_screen, keyboard_screen, shutdown_screen
    print(pos)
    
    if start_screen and pos[0] >= 145 and pos[0] <= 233 and pos[1] >= 85 and pos[1] <= 167:
        password2 = simpledialog.askstring('Welcome to Systems', 'Password?')
        paswrd2 = configure.get('password section 2', 'password2')
        paswrd2 = paswrd2.rstrip()
        paswrd2 = decode(paswrd2)
        if password2 == paswrd2:
            start_screen = False
            system_screen = True
            print('sfdfsfsdfsfsdfsf')
            #while not start_screen and system_screen:
            #    if pos[0] >= 315 and pos[0] <= 403 and pos[1] >= 85 and pos[1] <= 167:
            #        print('es')
    
while not failed:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            position = pygame.mouse.get_pos()
            if start_screen:
                check_mouse_pos(position)
    screen.blit(background, (0, 0))
    if first_time_password:
        screen.blit(background, (0, 0))
        pygame.display.update()
        password1 = simpledialog.askstring('Welcome to Doors Operating System', 'Password?')
        paswrd1 = configure.get('password section 1', 'password1')
        paswrd1 = paswrd1.rstrip()
        paswrd1 = decode(paswrd1)
        if password1 == paswrd1:
            print('yay dun')
            first_time_password = False
            if not complete:
                if start_screen and not system_screen:
                    screen.blit(system, (145, 85))
                elif not start_screen and system_screen:
                    screen.blit(shutdown, (315, 85))
        else:
            messagebox.showinfo('Error 001', 'LOL NOOB YOU FAILED ROFL LOL NOOB HAHA LOOK AT YOUR FACE IT LOOKS LIKE DEATH ROFL LOL')
            pygame.quit()
            sys.exit()
    else:
        if not complete:
            if start_screen and not system_screen:
                screen.blit(system, (145, 85))
            elif not start_screen and system_screen:
                screen.blit(shutdown, (315, 85))

        pygame.display.flip()
        pygame.display.update()

First, I load my images, which work fine. Next, I defined a function decode that decodes my base 64 encoded passwords. Then, I define a function check_mouse_pos that actually checks if the mouse has clicked on the image. Finally, I made a while loop that detects if I clicked my mouse.

I'm pretty new in Pygame, so this question my seem trivial :(

To answer your question, it's not working because once start_screen becomes False, the function check_mouse_pos() doesn't do much.

Anytime you have a collection of things, like buttons, pause and think to yourself: "How can I handle all of these with one section of code?"

Your program has the concept of a set of buttons, some of which are shown at different phases of the system access.

So probably your button has some attributes: Access-Level, Name, Image, Size, Location. I'm assuming (guessing) that as the user progresses through the various logons, more buttons become available. To keep it simple, let's make the access an integer, with 0 meaning "logged out", and increasing from there.

This leads to perhaps tuples of:

logon_butt = ( 0, "Logon",  "logon_button.png", pygame.Rect(   0,0,   128,128) )
exit_butt  = ( 0, "Exit",   "exit_button.png",  pygame.Rect( 160,0,   128,128) )
door1_butt = ( 1, "Door 1", "door.png",         pygame.Rect(   0,160, 128,128) )
door2_butt = ( 1, "Door 2", "door.png",         pygame.Rect( 160,160, 128,128) )
...

Or a class:

class Button:
    def __init__( self, access, name, image_filename, location, size )
        self.access = access
        self.name   = name
        self.image  = pygame.image.load( image_filename )
        self.image  = pygame.transform.smoothscale( image, size )
        self.rect   = self.image.get_rect()
        self.rect.x = location[0]
        self.rect.y = location[1]

logon_butt = Button( 0, "Logon", "logon_button.png", ( 0,0 ),     (128,128) )
exit_butt  = Button( 0, "Exit",  "exit_button.png",  ( 160,0 ),   (128,128) )
door1_butt = Button( 1, "Door1", "door.png",         ( 0,160 ),   (128,128) )
door2_butt = Button( 1, "Door2", "door.png",         ( 160,160 ), (128,128) )
...

Once you have a tuple or class to hold all the fields, your code can make a list of all buttons:

all_buttons = [ logon_butt, exit_butt, door1_butt, door2_butt ]  # etc.

When the user completes a password, the access-level number stored in user_access_level increases. So at 0 they can only exit or login.

The list makes it very easy to check every button each time you get a mouse-click event:

while not failed:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            position = pygame.mouse.get_pos()
            # check which button was pressed
            for butt in all_buttons:
                if ( butt.rect.collidepoint( position ) ):     # click inside button 
                    print( "Button [" + butt.name +"] pressed" )
                    if ( butt.access <= user_access_level ):   # is user allowed?
                        print( "User access OK" )

                    else:
                        print( "No ACCESS" )
                        # TODO - another login level?

The above code uses the Button class, but alternatively it could have used the tuple like butt[0] for access, and butt[1] for name, etc.

The button list also simplifies drawing all the buttons to the screen:

# repaint screen
screen.blit( background, (0, 0) )

# draw any buttons the user has access to
for butt in all_buttons:
    if ( butt.access <= user_access_level ):
        screen.blit( butt.image, butt.rect )

pygame.display.flip()

BTW: you only need to call pygame.display.flip() (or .update() ) once in the main loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM