Как бы я сделал эту кнопку, чтобы она регистрировала только один клик - PullRequest
1 голос
/ 09 апреля 2019

Я создал этот класс кнопок, который выполняет различные действия в зависимости от того, какая кнопка нажата.В момент нажатия кнопок действия выполняются несколько раз.Есть ли способ сделать так, чтобы действие выполнялось только один раз.

def action_button(x,y,w,h,ic,ac,text, text_colour,action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(screen, ac,(x,y,w,h))

        if click[0] == 1 and action != None:
            action()
    else:
        pygame.draw.rect(screen, ic,(x,y,w,h))

    font = pygame.font.SysFont("arial black",20)
    text = font.render(text,True,(text_colour))
    screen.blit(text,[x+w/2-(text.get_rect().w/2),y+h/2-(text.get_rect().h/2)])

1 Ответ

1 голос
/ 09 апреля 2019

Проблема pygame.mouse.get_pressed(), которая дает True все время, когда вы удерживаете кнопку мыши нажатой. Кнопка нажимает на нее как можно больше щелчков, и она выполняет функцию много раз. Используя event, вы можете поймать момент, когда состояние кнопки изменяется с не нажатой на нажатую, и это будет только один момент, поэтому она будет выполнять функцию только один раз.

Но при использовании события нужно много изменений. Если вы переместите все функции в for event цикл, тогда он будет запускать действие только один раз, но он также будет рисовать кнопку только один раз - когда вы нажимаете область, где должна быть кнопка.

Простой метод - разделить эту функцию на две функции

  • action_button_draw, который только рисует кнопку и использует ее в старом месте
  • action_button_click, который только запускает действие и помещает его в for event цикл

        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1: # 1 = left button, 3 = right button
                action_button_click(x, y, w, h, action)
    

    или хотя бы

        if event.type == pygame.MOUSEBUTTONDOWN:
            action_button_click(x, y, w, h, action)
    

Функция:

def action_button_click(x, y, w, h, action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        if click[0] == 1 and action != None:
            action()

def action_button_draw(x, y, w, h, ic, ac, text, text_colour):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(screen, ac,(x,y,w,h))
    else:
        pygame.draw.rect(screen, ic,(x,y,w,h))

    font = pygame.font.SysFont("arial black",20)
    text = font.render(text,True,(text_colour))
    screen.blit(text,[x+w/2-(text.get_rect().w/2),y+h/2-(text.get_rect().h/2)])

Минимальный рабочий пример:

import pygame

# --- constants ---

WIDTH = 640
HEIGHT = 480

FPS = 5

# --- functions ---

def action_button_click(x, y, w, h, action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        if click[0] == 1 and action != None:
            action()

def action_button_draw(x, y, w, h, ic, ac, text, text_colour):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(screen, ac,(x,y,w,h))
    else:
        pygame.draw.rect(screen, ic,(x,y,w,h))

    font = pygame.font.SysFont("arial black",20)
    text = font.render(text,True,(text_colour))
    screen.blit(text,[x+w/2-(text.get_rect().w/2),y+h/2-(text.get_rect().h/2)])

def test_action():
    print("clicked")

# --- main ---

# - init -

pygame.init()

screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen_rect = screen.get_rect()

# - mainloop -

clock = pygame.time.Clock()
running = True

while running:

    # - events -

    for event in pygame.event.get():

        if event.type == pygame.QUIT:
            running = False

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False

        # MOUSEBUTTONDOWN is created only once,
        # when button changes state from "not-pressed" to "pressed"
        # so it is better for this job than "pygame.mouse.get_pressed()"
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                action_button_click(100, 100, 100, 50, test_action)

    # --- draws ----

    screen.fill([0,0,0]) # clear screen

    action_button_draw(100, 100, 100, 50, [255,0,0], [0,255,0], "Hello", [0,0,0])

    pygame.display.flip()

    # - FPS -

    clock.tick(FPS)

# - end -

pygame.quit()

Эти две функции вы также можете поместить в класс и использовать класс, как в example-class.py

Оригинальная функция работает хорошо только в том случае, если выполненное действие удаляет кнопку из этого региона (т. Е. Удаляет меню и запускает игру), но имеет проблему, когда кнопка остается на том же месте после нажатия или вы помещаете новую кнопку в то же место (т.е. при переходе от меню к опциям, в которых кнопка находится там же)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...