У меня возникли проблемы при попытке переместить овал с помощью TKinter

#python #tkinter #tkinter-canvas

#python #tkinter #tkinter-canvas

Вопрос:

я начинаю использовать TKinter и пытаюсь создать несколько прыгающих шаров в качестве тренировочного упражнения. Когда я создаю уникальный овал и заставляю его двигаться, все работает, но когда я создаю класс Ball с методом move в нем, шар вообще не движется. Я не получаю сообщения об ошибке, но он отказывается перемещаться.

 """
Initialisation
"""
from tkinter import *
import time

w_height    = 600
w_width     = 800
xspeed      = 10
yspeed      = 10

window = Tk()
window.geometry ("{}x{}".format(w_width, w_height))
window.title("Bouncing Balls")
canvas = Canvas(window, width = w_width - 50,height = w_height - 50, bg="black")


"""
If i create the ball like that and make it move it works fine
"""

ball1 = canvas.create_oval(10, 10, 50, 50, fill ="red")
while True:
    canvas.move(ball1, xspeed, yspeed)
    window.update()
    time.sleep(0.05)
"""
But if i try to create the ball using a class it doesn't work anymore...
"""

class Ball:
    def __init__(self, posx, posy, r):
        canvas.create_oval(posx-r, posy-r, posx r, posy r, fill ="red")

    def move(self, dx, dy):
        canvas.move(self, dx, dy)

ball1 = Ball(50,50,10)

while True:
    ball1.move(xspeed, yspeed)
    window.update()
    time.sleep(0.05)
  

Я думал, что это даст тот же результат, но в первом случае шарик движется, а во втором — нет, и я не могу понять почему.

Ответ №1:

В вашем коде canvas.create_oval() функция возвращает объект, который затем может быть перемещен моей вызываемой canvas.move(object, ...) функцией. Но, как вы можете видеть, вы передаете self в методе класса move .

 def move(self, dx, dy):
    canvas.move(*self*, dx, dy)
  

Это экземпляр класса Ball, в данном случае ball1 переменной, которую вы определили (фактически переназначили), выполнив ball1 = Ball(50, 50, 10) .

Чтобы это заработало, измените свой класс на этот.

 class Ball:

    def __init__(self, posx, posy, r):
        self.ball = canvas.create_oval(posx-r, posy-r, posx r, posy r, fill ="red")

    def move(self, dx, dy):
        canvas.move(self.ball, dx, dy)
  

Здесь вы определяете поле класса, которое будет получать то, что возвращает canvas.create_oval() function and then use it to move the object.