Спасибо за вашу помощь, я ценю! Когда у меня возникнут проблемы, я поделюсь ими в командах. Кстати, я искал ваш проект OOP Button и заметил кое-что странное. Цвета кнопок не определены с помощью RGB, или есть изображение, позволяющее сделать цвета кнопок dodgerblue1, lightskyblue и aquamarine1. Эти цвета самостоятельно определены в python с помощью этих специальных ключевых слов или вы только что сделали трюк?

лал кнопки в Pygame для событий щелчка, но есть проблема. Когда я нажимаю кнопку мыши и перемещаю мышь между границами кнопки, событие щелчка повторяется. Я просто хочу один клик, пока я не отпущу кнопку мыши. Как я могу это сделать?

import pygame,time
pygame.init()
x,y = (200,300)
pencere = pygame.display.set_mode((x,y))
pygame.display.set_caption("Click")

white = (255,255,255)
black = (0,0,0)
black2 = (30,30,30)

class Counter:
    count = 0
    def click(self):
        self.count += 1

number = Counter()
def text_objects(text, font, color):
    textSurface = font.render(text, True, color)
    return textSurface, textSurface.get_rect()

def button(msg,x,y,w,h,c,ic,action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    pygame.draw.rect(pencere, c,(x,y,w,h))

    smallText = pygame.font.Font("freesansbold.ttf",20)
    textSurf, textRect = text_objects(msg, smallText, white)
    textRect.center = ( (x+(w/2)), (y+(h/2)) )
    pencere.blit(textSurf, textRect)

    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(pencere, ic,(x,y,w,h))
        if click[0] == 1 != None:
            action()
        smallText = pygame.font.Font("freesansbold.ttf",20)
        textSurf, textRect = text_objects(msg, smallText, white)
        textRect.center = ( (x+(w/2)), (y+(h/2)) )
        pencere.blit(textSurf, textRect)
def loop():
    cikis = False
    while not cikis:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                cikis = True
                pygame.quit()
                quit()
            pencere.fill(white)
            smallText = pygame.font.Font("freesansbold.ttf",50)
            textSurf, textRect = text_objects(str(number.count), smallText, black)
            textRect.center = ((x/2)), (30)
            pencere.blit(textSurf, textRect)
            button("Click",0,100,200,200,black,black2,number.click)
            pygame.display.update()
loop()
pygame.quit()
quit()
 furas04 дек. 2017 г., 20:24
 serge1peshcoff04 дек. 2017 г., 19:45
Можете ли вы предоставить код, который вы используете?
 Arda Altun04 дек. 2017 г., 21:58
я добавил коды. Как вы можете видеть, я использую pygame.mouse.get_pressed () - так что мне теперь делать? что я должен изменить в моих кодах?
 furas04 дек. 2017 г., 19:52
Кстати: вы используетеevent.type == MOUSEBUTTONDOWN или жеpygame.mouse.get_pressed() ? С участиемMOUSEBUTTONDOWN у вас не должно быть этой проблемы, потому что событие создается только тогда, когда кнопка мыши меняет состояние дляnot-pressed вpressed но он не создается, когда кнопка мыши удерживается нажатой.get_pressed() возвращаетсяTrue когда кнопка мыши удерживается нажатой.
 furas04 дек. 2017 г., 19:45
Вы должны добавить к переменной переменной т.е.clicked = True запомнить его и проверить перед выполнением функции, назначенной кнопке. И очистите его, когда отпустите кнопку мыши.

Ответы на вопрос(1)

Решение Вопроса

Код чертежа и кнопки должен быть не в цикле событий, а во внешнем цикле while. Вы звонитеbutton функционировать каждый раз, когда происходит событие (например, если мышь движется).

button функция делает слишком много. Он создает и стирает текстовые поверхности, рисует текты, проверяет наличие коллизий и вызываетclick метод.

Вы не должны использоватьpygame.mouse.get_pressed() и вместо этого обрабатыватьMOUSEBUTTONDOWN события в цикле событий.mouse.get_pressed просто проверяет, удерживается ли кнопка мыши, а не происходит ли один щелчок

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

import pygame


pygame.init()
width, height = (200,300)
screen = pygame.display.set_mode((width, height))

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (30, 30, 30)
FONT = pygame.font.Font("freesansbold.ttf", 50)


def loop():
    clock = pygame.time.Clock()
    number = 0
    # The button is just a rect.
    button = pygame.Rect(0, 100, 200, 200)
    done = False
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            # This block is executed once for each MOUSEBUTTONDOWN event.
            elif event.type == pygame.MOUSEBUTTONDOWN:
                # 1 is the left mouse button, 2 is middle, 3 is right.
                if event.button == 1:
                    # `event.pos` is the mouse position.
                    if button.collidepoint(event.pos):
                        # Increment the number.
                        number += 1

        screen.fill(WHITE)
        pygame.draw.rect(screen, GRAY, button)
        text_surf = FONT.render(str(number), True, BLACK)
        # You can pass the center directly to the `get_rect` method.
        text_rect = text_surf.get_rect(center=(width/2, 30))
        screen.blit(text_surf, text_rect)
        pygame.display.update()

        clock.tick(30)


loop()
pygame.quit()

Приложение: Я рекомендую использовать объектно-ориентированное решение сButton класс, который является подклассомpygame.sprite.Sprite и могут быть добавлены в группы спрайтов. Вы можете передать свои собственные изображенияButton класс или использовать изображения по умолчанию. Вы также должны передать функцию или метод обратного вызова каждому экземпляру кнопки, который будет вызываться вhandle_event метод для обновления определенных атрибутов игрового класса (здесь у меня есть метод, который увеличивает счетчик и еще один, чтобы выйти из игры).

import pygame as pg


pg.init()
screen = pg.display.set_mode((800, 600))
FONT = pg.font.SysFont('Comic Sans MS', 32)
# Default button images/pygame.Surfaces.
IMAGE_NORMAL = pg.Surface((100, 32))
IMAGE_NORMAL.fill(pg.Color('dodgerblue1'))
IMAGE_HOVER = pg.Surface((100, 32))
IMAGE_HOVER.fill(pg.Color('lightskyblue'))
IMAGE_DOWN = pg.Surface((100, 32))
IMAGE_DOWN.fill(pg.Color('aquamarine1'))


# Button is a sprite subclass, that means it can be added to a sprite group.
# You can draw and update all sprites in a group by
# calling `group.update()` and `group.draw(screen)`.
class Button(pg.sprite.Sprite):

    def __init__(self, x, y, width, height, callback,
                 font=FONT, text='', text_color=(0, 0, 0),
                 image_normal=IMAGE_NORMAL, image_hover=IMAGE_HOVER,
                 image_down=IMAGE_DOWN):
        super().__init__()
        # Scale the images to the desired size (doesn't modify the originals).
        self.image_normal = pg.transform.scale(image_normal, (width, height))
        self.image_hover = pg.transform.scale(image_hover, (width, height))
        self.image_down = pg.transform.scale(image_down, (width, height))

        self.image = self.image_normal  # The currently active image.
        self.rect = self.image.get_rect(topleft=(x, y))
        # To center the text rect.
        image_center = self.image.get_rect().center
        text_surf = font.render(text, True, text_color)
        text_rect = text_surf.get_rect(center=image_center)
        # Blit the text onto the images.
        for image in (self.image_normal, self.image_hover, self.image_down):
            image.blit(text_surf, text_rect)

        # This function will be called when the button gets pressed.
        self.callback = callback
        self.button_down = False

    def handle_event(self, event):
        if event.type == pg.MOUSEBUTTONDOWN:
            if self.rect.collidepoint(event.pos):
                self.image = self.image_down
                self.button_down = True
        elif event.type == pg.MOUSEBUTTONUP:
            # If the rect collides with the mouse pos.
            if self.rect.collidepoint(event.pos) and self.button_down:
                self.callback()  # Call the function.
                self.image = self.image_hover
            self.button_down = False
        elif event.type == pg.MOUSEMOTION:
            collided = self.rect.collidepoint(event.pos)
            if collided and not self.button_down:
                self.image = self.image_hover
            elif not collided:
                self.image = self.image_normal


class Game:

    def __init__(self, screen):
        self.done = False
        self.clock = pg.time.Clock()
        self.screen = screen
        # Contains all sprites. Also put the button sprites into a
        # separate group in your own game.
        self.all_sprites = pg.sprite.Group()
        self.number = 0
        # Create the button instances. You can pass your own images here.
        self.start_button = Button(
            320, 70, 170, 65, self.increment_number,
            FONT, 'Increment', (255, 255, 255),
            IMAGE_NORMAL, IMAGE_HOVER, IMAGE_DOWN)
        # If you don't pass images, the default images will be used.
        self.quit_button = Button(
            320, 240, 170, 65, self.quit_game,
            FONT, 'Quit', (255, 255, 255))
        # Add the button sprites to the sprite group.
        self.all_sprites.add(self.start_button, self.quit_button)

    def quit_game(self):
        """Callback method to quit the game."""
        self.done = True

    def increment_number(self):
        """Callback method to increment the number."""
        self.number += 1
        print(self.number)

    def run(self):
        while not self.done:
            self.dt = self.clock.tick(30) / 1000
            self.handle_events()
            self.run_logic()
            self.draw()

    def handle_events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.done = True
            for button in self.all_sprites:
                button.handle_event(event)

    def run_logic(self):
        self.all_sprites.update(self.dt)

    def draw(self):
        self.screen.fill((30, 30, 30))
        self.all_sprites.draw(self.screen)
        pg.display.flip()


if __name__ == '__main__':
    pg.init()
    Game(screen).run()
    pg.quit()

Приложение 2: Промежуточное решение с кнопками в качестве словарей. Можно также использовать списки, но словари более читабельны.

import pygame


pygame.init()

WHITE = (255, 255, 255)
ACTIVE_COLOR = pygame.Color('dodgerblue1')
INACTIVE_COLOR = pygame.Color('dodgerblue4')
FONT = pygame.font.Font(None, 50)


def draw_button(button, screen):
    """Draw the button rect and the text surface."""
    pygame.draw.rect(screen, button['color'], button['rect'])
    screen.blit(button['text'], button['text rect'])


def create_button(x, y, w, h, text, callback):
    """A button is a dictionary that contains the relevant data.

    Consists of a rect, text surface and text rect, color and a
    callback function.
    """
    # The button is a dictionary consisting of the rect, text,
    # text rect, color and the callback function.
    text_surf = FONT.render(text, True, WHITE)
    button_rect = pygame.Rect(x, y, w, h)
    text_rect = text_surf.get_rect(center=button_rect.center)
    button = {
        'rect': button_rect,
        'text': text_surf,
        'text rect': text_rect,
        'color': INACTIVE_COLOR,
        'callback': callback,
        }
    return button


def main():
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    done = False

    number = 0

    def increment_number():  # A callback function for the button.
        """Increment the `number` in the enclosing scope."""
        nonlocal number
        number += 1
        print(number)

    def quit_game():  # A callback function for the button.
        nonlocal done
        done = True

    button1 = create_button(100, 100, 250, 80, 'Click me!', increment_number)
    button2 = create_button(100, 200, 250, 80, 'Me too!', quit_game)
    # A list that contains all buttons.
    button_list = [button1, button2]

    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            # This block is executed once for each MOUSEBUTTONDOWN event.
            elif event.type == pygame.MOUSEBUTTONDOWN:
                # 1 is the left mouse button, 2 is middle, 3 is right.
                if event.button == 1:
                    for button in button_list:
                        # `event.pos` is the mouse position.
                        if button['rect'].collidepoint(event.pos):
                            # Increment the number by calling the callback
                            # function in the button list.
                            button['callback']()
            elif event.type == pygame.MOUSEMOTION:
                # When the mouse gets moved, change the color of the
                # buttons if they collide with the mouse.
                for button in button_list:
                    if button['rect'].collidepoint(event.pos):
                        button['color'] = ACTIVE_COLOR
                    else:
                        button['color'] = INACTIVE_COLOR

        screen.fill(WHITE)
        for button in button_list:
            draw_button(button, screen)
        pygame.display.update()
        clock.tick(30)


main()
pygame.quit()
 skrx07 дек. 2017 г., 02:16
Пример ООП добавлен. Если вы еще не работали со спайтами и группами Pygame, взгляните наэтот урок.
 Arda Altun08 дек. 2017 г., 17:15
Спасибо за вашу помощь, я ценю! Когда у меня возникнут проблемы, я поделюсь ими в командах. Кстати, я искал ваш проект OOP Button и заметил кое-что странное. Цвета кнопок не определены с помощью RGB, или есть изображение, позволяющее сделать цвета кнопок dodgerblue1, lightskyblue и aquamarine1. Эти цвета самостоятельно определены в python с помощью этих специальных ключевых слов или вы только что сделали трюк?
 Arda Altun06 дек. 2017 г., 13:40
Огромное спасибо!! И да, я сделаю несколько кнопок, поэтому мне нужна помощь в вашем примере ООП.
 Arda Altun07 дек. 2017 г., 22:47
Спасибо большое skrx, но есть проблема со мной, мой основной язык не английский, и я не слишком много знаю классы. Я все еще учусь, поэтому я не могу понять их слишком много. Но я постараюсь понять это. Кстати, есть ли шанс в любое время получить от вас помощь по поводу моих кодов?
 skrx08 дек. 2017 г., 00:02
Лучше просто опубликовать новый вопрос здесь или на другом форуме, например, reddit.com/r/learnpython (если вопрос не подходит для SO), тогда больше людей смогут увидеть его и помочь вам. Кроме того, глава 12 связанного руководства посвящена классам, поэтому вам следует сначала прочитать ее, если вы не знаете ООП.

Ваш ответ на вопрос