События Python Turtle с несколькими нажатиями

Я пытаюсь сделать черепашью версию 8-Queens Puzzle, используя Python Turtle.

Я начал, но попал в блок из-за того, что событие click для пользовательского объекта Turtle, кажется, срабатывает только один раз. Я знаю, что события щелчка экрана запускаются несколько раз, так это особенность экземпляров Turtle? Что мне не хватает, пожалуйста?

import turtle

screen = turtle.Screen()
screen.reset()
SIZE = 40
screen.register_shape('box', ((-SIZE/2, SIZE/2), (SIZE/2, SIZE/2), (SIZE/2, -SIZE/2), (-SIZE/2, -SIZE/2)))
screen.register_shape('images/queenlogo40x40.gif')

class Box(turtle.Turtle):
    def __init__(self, x=0, y=0, place_color='green'):
        super(Box, self).__init__()
        self.place_color = place_color
        self.speed(0)
        self.penup()
        self.shape("box")
        self.color(place_color)
        self.setpos(x, y)
        self.has_queen = False
        self.onclick(self.click_handler)

    def click_handler(self, x, y):
        print("start:" , self.has_queen)

        if self.has_queen:
            self.shape('box')
            self.has_queen = False
        else:
            self.shape('images/queenlogo40x40.gif')
            self.has_queen = True

        print("end:" , self.has_queen)


    def __str__(self):
        """ Print piece details """
        return "({0}, {1}), {2}".format(self.xcor(), self.ycor(), self.place_color())

Изменить: я могу это исправить, добавив self.onclick(self.click_handler) обработчику щелчков, но это только кажется неправильным. Я уверен, что видел подобные функции без необходимости перепривязывать событие каждый раз, когда оно используется.

1 ответ

Ваш пример должен работать правильно, я не вижу концептуальной проблемы.

Но есть череп в черепахе. Информация о onclick хранится на черепахе _item имущество:

self.screen._onclick(self.turtle._item, fun, btn, add)

Но когда вы изменяете форму черепахи с изображения на многоугольник или наоборот, это разрушает _item имущество:

if self._type in ["image", "polygon"]:
        screen._delete(self._item)

Так что ваша привязка потеряна. Обратите внимание, что если вы измените строку:

self.shape('images/queenlogo40x40.gif')

вместо этого:

self.shape('turtle')

код работает нормально, так как вы переходите от многоугольника к многоугольнику и _item сохраняется Итак, добавление self.onclick(self.click_handler) после изменения формы необходимо при переходе между полигоном и изображением.

Я переработал ваш код чуть ниже, чтобы решить пару не связанных проблем (например, исправлено super() вызов для Python 3; удалены неверные символы в __str__() код.)

from turtle import Turtle, Screen

SIZE = 40

class Box(Turtle):
    def __init__(self, x=0, y=0, place_color='green'):
        super().__init__('box')

        self.speed('fastest')
        self.color(place_color)
        self.place_color = place_color
        self.has_queen = False
        self.penup()
        self.setpos(x, y)

        self.onclick(self.click_handler)

    def click_handler(self, x, y):

        print("start:", self.has_queen)

        if self.has_queen:
            self.shape('box')
        # else:
            # self.shape('turtle')
        else:
            self.shape('queenlogo40x40.gif')

        self.has_queen = not self.has_queen
        self.onclick(self.click_handler)  # redo since self.shape() may undo this

        print("end:", self.has_queen)

    def __str__(self):
        """ Print piece details """
        return "({0}, {1}), {2}".format(self.xcor(), self.ycor(), self.place_color)

screen = Screen()
screen.register_shape('box', ((-SIZE/2, SIZE/2), (SIZE/2, SIZE/2), (SIZE/2, -SIZE/2), (-SIZE/2, -SIZE/2)))
screen.register_shape('queenlogo40x40.gif')

tortoise = Box()

screen.mainloop()
Другие вопросы по тегам