Python 在 Tkinter Canvas 中移动球
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25430786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Moving balls in Tkinter Canvas
提问by dlohse
This is a very basic program with which I want to make two moving balls, but only one of them actually moves.
这是一个非常基本的程序,我想用它制作两个移动的球,但实际上只有一个球在移动。
I have tried some variations as well but can't get the second ball moving; another related question - some people use the move(object)method to achieve this, while others do a delete(object)and then redraw it. Which one should I use and why?
我也尝试了一些变化,但无法让第二个球移动;另一个相关问题-有些人使用该move(object)方法来实现此目的,而其他人则使用该方法delete(object)然后重新绘制它。我应该使用哪一种,为什么?
This is my code that is only animating/moving one ball:
这是我的代码,它只对一个球进行动画/移动:
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()
回答by Cory Kramer
This function seems to be the culprit
这个函数似乎是罪魁祸首
def move_ball(self):
while True:
self.canvas.move(self.ball, 2, 1)
self.canvas.after(20)
self.canvas.update()
You deliberately put yourself in an infinite loop when you call it.
当你调用它时,你故意将自己置于无限循环中。
ball1.move_ball() # gets called, enters infinite loop
ball2.move_ball() # never gets called, because code is stuck one line above
回答by sundar nataraj
try
instead of self.canvas.move(self.ball, 2, 1)use
尝试而不是 self.canvas.move(self.ball, 2, 1)使用
self.canvas.move(ALL, 2, 1)
All this used to move all the objects in canvas
所有这些都用于移动画布中的所有对象
回答by Donald
Its only moving one because the program reads only one variable at a time. If you set the program to read when the ball gets to a certain spot, say the end of the canvas, you could then code the program to read the next line and trigger the second ball to move. But, this will only move one at a time.
它只移动一个,因为程序一次只读取一个变量。如果您将程序设置为在球到达某个位置(例如画布的末端)时读取,则您可以编写程序以读取下一行并触发第二个球移动。但是,这一次只能移动一个。
Your program is literally stuck on the line:
您的程序实际上卡在线上:
ball1.move_ball()
ball1.move_ball()
And it will never get to line:
它永远不会上线:
ball2.move_ball()
ball2.move_ball()
Because there isn't a limit to where the loop should end.
因为循环结束的位置没有限制。
Otherwise, the answer by "sundar nataraj" will do it.
否则,“sundar nataraj”的回答会做到。
回答by Bryan Oakley
You should never put an infinite loop inside a GUI program -- there's already an infinite loop running. If you want your balls to move independently, simply take out the loop and have the move_ballmethod put a new call to itself on the event loop. With that, your balls will continue to move forever (which means you should put some sort of check in there to prevent that from happening)
永远不要在 GUI 程序中放置无限循环——已经有一个无限循环在运行。如果您希望您的球独立移动,只需取出循环并让该move_ball方法在事件循环中对其自身进行新调用。这样,您的球将永远继续移动(这意味着您应该在那里进行某种检查以防止这种情况发生)
I've modified your program slightly by removing the infinite loop, slowing down the animation a bit, and also using random values for the direction they move. All of that changes are inside the move_ballmethod.
我通过删除无限循环、稍微减慢动画速度以及对它们移动的方向使用随机值来稍微修改您的程序。所有这些变化都在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()

