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ゼロなのでself.yPos-59ですが、デフォルトの上部y座標は0であるため、画面外に描画しています.

コードには他にも多くの問題があります。最も厄介なのは、あなたがtime.sleep思っていることを正確に実行する呼び出しを行っていることです。これにより、プログラム全体がスリープ状態になります。GUI のメイン スレッドを呼び出してはいけません。time.sleep

レースの各瞬間のオブジェクトを削除して再作成しようとしています。ただし、実際には何も消去していません。単に隠しているだけです。deleteオブジェクトを消去するには、キャンバスのメソッドを呼び出す必要があります。また、キャンバスにはmoveアイテムを移動するために使用できるメソッドがあることをご存知ですか? そのため、それらを削除して再作成する必要はありません。一度馬を描いてから、 を呼び出しmoveて画面上を移動するだけです。

最後に、無限ループを実行しており、そのループでupdate. これは通常、このような単純なプログラムでは機能しますが、Tkinter でアニメーションを行うには間違ったアプローチです。経験則として、呼び出しupdateてはいけない理由がわかっている場合を除き、直接呼び出してはならないということですupdate(それでも、呼び出しが正しいことはめったにありません)。

ループの代わりに、while Trueすべてを 1 回移動する関数を作成し、それを 1 秒 (または 0.5 秒など) に 1 回呼び出すように手配する必要があります。パターンは次のようになります。

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)

(もちろん、私はよりオブジェクト指向スタイルのアプローチを提唱していますが、単純にするためにそれを省略しました)

于 2013-04-09T20:20:37.920 に答える