我的目标是创建一个模拟赛马的程序,我的问题是当我用Tkinter画画时,我得到一个空白的画布。我确定它有一些明显的错误,但我找不到它。有什么帮助吗?
class Horse ():
def __init__ (self, color, number, slot):
self.xPos = 0
self.yPos = self.xPos - 59
self.move = 0
self.slot = slot
self.size = 40
self.color = color
self.number = number
def horseMove (self):
self.Erase()
self.move= random.randint(20,80)
self.xPos = self.xPos + self.move
self.Draw()
myCanvas.update()
return self.xPos
def Erase (self):
myCanvas.create_rectangle (self.xPos, self.yPos, self.xPos + 75, self.yPos + 40, fill = 'white', outline ='white')
def Draw (self):
myCanvas.create_oval (self.xPos, self.yPos, self.xPos + 75, self.yPos + 40, fill = color)
myCanvas.create_text (self.xPos + 35, self.yPos, text = self.number, fill = 'blue', font = ("Times","17"))
time.sleep (0.5)
这是我的班级代码
Horses= []
slot=0
for i in range (0,3):
number=input("what is the horses number: ")
color=input("what is the horses color: ")
slot += 1
animal=Horse(color, number, slot)
Horses.append(animal)
import random
from tkinter import *
import time
root = Tk()
myCanvas = Canvas (root, width =1000, height=1000, background='white')
myCanvas.pack()
while True:
for i in range (0,len(Horses)):
animal.horseMove()
这是我的主线
答案 0 :(得分:1)
您的代码中存在很多问题。要解决为什么你得到一个空白画布的具体问题,这是因为你因为这条线而将马对象从屏幕上绘制出来:
self.yPos = self.xPos - 59
self.xPos
为零,因此self.yPos
为-59,但默认的上y坐标为0,因此您将从屏幕上绘制。
您的代码中还有许多其他问题。最令人不安的是,你正在调用time.sleep
,它完全符合你的想法 - 它会导致整个程序进入睡眠状态。你应该从不在GUI的主线程中调用time.sleep
。
您正在(尝试)删除并重新创建比赛的每个时刻的对象。但是,你实际上并没有删除任何东西,你只是隐藏它。您应该调用画布的delete
方法来擦除对象。另外,您是否知道画布有move
方法可用于移动项目?因此,您无需删除并重新创建它们 - 只需绘制一次马,然后调用move
将其移动到屏幕上。
最后,你正在进行一个无限循环,并在该循环中调用update
。虽然这通常适用于这样一个简单的程序,但使用Tkinter进行动画是错误的方法。一个好的经验法则是你永远不应该直接打电话给update
,除非你知道为什么你不应该打电话给update
(即便如此,它也很少是正确的事情)
而不是while True
循环,你需要编写一个移动所有东西一次的函数,然后安排每秒调用一次(或半秒,无论如何)。模式看起来像这样:
def draw_one_frame():
<do whatever you need to do to move each item once>
root.after(500, self.draw_one_frame)
通常你有某种“启动”功能可以调用它一次,然后再调用它自己再次调用它。通常,您将有一个“停止”按钮,该按钮调用函数来设置标志,并检查该标志以最终停止动画。所以,最终版本更像是:
def start():
running = True
draw_one_frame()
def stop():
running = False
def draw_one_frame():
if running:
<do whatever...>
root.after(500, self.draw_one_frame)
(当然,我提倡更多OO风格的方法,但我把它留给了简单的方法)