0

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

这是我的主线

4

1 回答 1

1

您的代码中有很多问题。为了解决为什么你得到一个空白画布的具体问题,这是因为你因为这条线而将马对象从屏幕上画了出来:

    self.yPos = self.xPos - 59

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

您的代码中还有许多其他问题。最令人不安的是,你调用time.sleep的正是你认为的那样——它会导致你的整个程序进入休眠状态。你永远不应该调用time.sleepGUI 的主线程。

您正在(试图)在比赛的每一刻删除并重新创建对象。但是,您实际上并没有擦除任何内容,而只是将其隐藏了。您应该调用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 风格的方法,但为了简单起见,我省略了它)

于 2013-04-09T20:20:37.920 回答