用我的python类绘制问题

时间:2013-04-09 17:15:27

标签: python tkinter

我的目标是创建一个模拟赛马的程序,我的问题是当我用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()

这是我的主线

1 个答案:

答案 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风格的方法,但我把它留给了简单的方法)