2013-04-09 40 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