2013-04-09 46 views
0

我的目标是创建一个模拟赛马的程序,我的问题是当我用Tkinter绘制时,我得到一个空白画布。我确定它有一些明显的错误,但我找不到它。任何帮助?有问题用我的Python类绘图

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

您有好几个问题,即''myCanvas'没有在Horse类中定义,这是一个无限循环,它会锁定你的程序,并且为我在范围内(0,len(Horses)):'不使用'i'的循环。从简单的事情开始。 – 2013-04-09 17:28:10

回答

1

你在你的代码中的许多问题。要了解为什么你得到一个空白的画布的具体问题,这是因为你画马关的对象,因为这条线的画面:

self.yPos = self.xPos - 59 

self.xPos是零,所以self.yPos是-59,但默认的顶部y坐标是0,所以你正在画屏幕。

你的代码还有很多其他问题。最令人不安的是你打电话给time.sleep,它确实如你所想的那样 - 它会导致你的整个程序进入睡眠状态。您应该在图形用户界面的主线程中从未调用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风格的做法,但我离开了这一点,以让事情变得简单)

+0

移动方法如何工作?有没有可以链接的教程? – 2013-04-10 16:25:00

+0

@ArkAngel:没什么。您只需调用它,告诉它要使用哪个项目以及在X和Y方向上移动多少。 – 2013-04-10 16:29:05