在Tkinter Canvas中移动球体

9 投票
4 回答
29292 浏览
提问于 2025-04-18 18:05

这是一个非常基础的程序,我想让两个小球移动,但实际上只有一个小球在动。

我也尝试了一些不同的方法,但就是无法让第二个小球动起来。还有一个相关的问题是,有些人使用 move(object) 方法来实现这个效果,而另一些人则是先 delete(object) 然后再重新绘制它。我应该用哪种方法,为什么呢?

这是我目前的代码,只能让一个小球动:

from Tkinter import *

class Ball:
    def __init__(self, canvas, x1, y1, x2, y2):
    self.x1 = x1
    self.y1 = y1
    self.x2 = x2
    self.y2 = y2
    self.canvas = canvas
    self.ball = canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill="red")

    def move_ball(self):
        while True:
            self.canvas.move(self.ball, 2, 1)
            self.canvas.after(20)
            self.canvas.update()

# initialize root Window and canvas
root = Tk()
root.title("Balls")
root.resizable(False,False)
canvas = Canvas(root, width = 300, height = 300)
canvas.pack()

# create two ball objects and animate them
ball1 = Ball(canvas, 10, 10, 30, 30)
ball2 = Ball(canvas, 60, 60, 80, 80)

ball1.move_ball()
ball2.move_ball()

root.mainloop()

4 个回答

0

试试用这个,别用 self.canvas.move(self.ball, 2, 1)

self.canvas.move(ALL, 2, 1)

这样做可以移动画布上的所有物体。

2

程序只移动一个球,是因为它一次只读取一个变量。如果你设置程序在球到达某个特定位置时,比如画布的边缘,去读取下一个变量,那么你可以编写代码让程序读取下一行,从而触发第二个球移动。不过,这样的话,还是只能一个一个地移动。

你的程序实际上卡在这一行:

ball1.move_ball()

它永远不会执行到这一行:

ball2.move_ball()

这是因为循环没有设置结束的条件。

否则,"sundar nataraj"的回答可以解决这个问题。

3

这个函数看起来是问题的根源。

def move_ball(self):
    while True:
        self.canvas.move(self.ball, 2, 1)
        self.canvas.after(20)
        self.canvas.update()

当你调用它的时候,你故意让自己陷入了一个无限循环。

ball1.move_ball()    # gets called, enters infinite loop
ball2.move_ball()    # never gets called, because code is stuck one line above
16

在图形用户界面(GUI)程序中,绝对不要放一个无限循环,因为程序本身已经在运行一个无限循环了。如果你想让你的球独立移动,只需去掉那个循环,让move_ball方法在事件循环中自己再调用一次。这样一来,球就会一直移动,直到应用程序被关闭。

我稍微修改了一下你的程序,去掉了无限循环,把动画速度放慢了一点,并且让球的移动方向变得随机。这些改动都在move_ball方法里。

from Tkinter import *
from random import randint

class Ball:
    def __init__(self, canvas, x1, y1, x2, y2):
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2
        self.canvas = canvas
        self.ball = canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill="red")

    def move_ball(self):
        deltax = randint(0,5)
        deltay = randint(0,5)
        self.canvas.move(self.ball, deltax, deltay)
        self.canvas.after(50, self.move_ball)

# initialize root Window and canvas
root = Tk()
root.title("Balls")
root.resizable(False,False)
canvas = Canvas(root, width = 300, height = 300)
canvas.pack()

# create two ball objects and animate them
ball1 = Ball(canvas, 10, 10, 30, 30)
ball2 = Ball(canvas, 60, 60, 80, 80)

ball1.move_ball()
ball2.move_ball()

root.mainloop()

撰写回答