Python3 Tkinter and Pillow: как повернуть изображение, пока оно находится на холсте - PullRequest
0 голосов
/ 10 июля 2020

Я хочу переместить черепаху по холсту, щелкнув по холсту, и черепаха должна указывать в направлении своего движения. Движущаяся часть работает, но функция поворота вызывает искажение и искажение изображения.

Что я делаю неправильно и как это исправить?

У меня есть класс, который добавляет изображение черепахи на холст:

class TurtleImage:
    """
    A Turtle image that will be placed on the canvas that is given in the ctor.
    The turtle can be moved around the canvas with the move() method.
    """

    def __init__(self, canvas : Canvas):
        self.__turtle_file : str = self.__find_file("turtle_example/turtle.png")
        self.__canvas = canvas
        self.__pilImage : PngImagePlugin.PngImageFile = PILImage.open(self.__turtle_file)
        self.__pilTkImage : ImageTk.PhotoImage = ImageTk.PhotoImage(self.__pilImage)
        self.__turtle_id : int = canvas.create_image(100,100, image=self.__pilTkImage)
        self.__is_moving = False

Этот класс также имеет метод для анимации движения черепахи по холсту. Он перемещает черепаху на 1 пиксель в направлении x, y или в обоих направлениях, а затем планирует повторный вызов после задержки, определяемой параметром скорости. Он также должен повернуть черепаху так, чтобы она указывала в правильном направлении:

def move(self, dest_x : int, dest_y :int, speed : float = 0.1):
    self.__is_moving = True
    delay_ms = math.floor(1/speed)
    current_x, current_y = self.__canvas.coords(self.__turtle_id)

    delta_x = 1 if current_x < dest_x else -1 if current_x > dest_x else 0
    delta_y = 1 if current_y < dest_y else -1 if current_y > dest_y else 0
    angle = math.atan2(delta_y,delta_x)

    self.__rotate(angle)

    if (delta_x, delta_y) != (0, 0):
        self.__canvas.move(self.__turtle_id, delta_x, delta_y)

    if (current_x, current_y) != (dest_x, dest_y):
        self.__canvas.after(delay_ms, self.move, dest_x, dest_y, speed)
    else:
        self.__is_moving = False

Поскольку холст не имеет возможности вращать свои объекты, я должен заменить объект повернутой версией самого себя:

def __rotate(self, angle : float):
    self.__pilImage = self.__pilImage.rotate(angle)
    self.__pilTkImage = ImageTk.PhotoImage(self.__pilImage)
    self.__replace_image(self.__pilTkImage)

def __replace_image(self, new_image : ImageTk.PhotoImage):
    self.__canvas.itemconfig(self.__turtle_id, image = new_image)

Движение работает нормально, но функция поворота приводит к искажению и искажению изображения, и оно становится хуже каждый раз при вызове.

Вы можете сказать мне, почему это не так? не работает, и что мне нужно сделать, чтобы это исправить?

Вот скриншот указанной черепахи до и после поворота:

enter image description here введите описание изображения здесь

1 Ответ

0 голосов
/ 10 июля 2020

Я нашел решение, мне нужно заново открыть файл:

def __rotate(self, angle : float):
    self.__pilImage = PILImage.open(self.__turtle_file)
    self.__pilImage = self.__pilImage.rotate(angle)
    self.__pilTkImage = ImageTk.PhotoImage(self.__pilImage)
    self.__replace_image(self.__pilTkImage)

Я не знаю почему.

...