2016-02-02 64 views
0

我正在一個gui上動畫,一次連續動畫一個。 我有兩個類cointoss.py和flipbell.py。使用tkinter在Python中更新畫布上的多個橢圓座標

Cointoss類爲硬幣生成值更改,並使用觸發器來爲流程設置動畫。

就好像現在我的代碼一次只能動畫一個硬幣,而不是一次硬幣。

當我說所有的硬幣這是邏輯:第一個硬幣根據價值變化下降,接下來另一個下來,但第一個硬幣值也相應地更新等等。

我需要幫助如何繼續我迄今爲止的嘗試。我已經使用循環來激活過程,我正在考慮使用遞歸方法來獲得邏輯部分。

任何幫助現有的代碼或想法前進會很好。

flipbell.py

from tkinter import Tk, Canvas, Button, W, E 
import random 
from math import pi, sin, cos 
from cointoss import * 


class FlipBell(object): 
    """ 
    GUI to simulate cointoss. 
    """ 
    def __init__(self, wdw, dimension, increment, delay): 
     """ 
     Determines the layout of the GUI. 
     wdw : top level widget, the main window, 
     dimension : determines the size of the canvas, 
     increment : step size for a billiard move, 
     delay : time between updates of canvas. 
     """ 
     wdw.title('Coin flips and Bell Curve') 
     self.dim = dimension # dimension of the canvas 
     self.inc = increment 
     self.dly = delay 
     self.togo = False # state of animation 
     # initial coordinates of the ball 
     self.xpt = self.dim/2 
     self.ypt = 0 
     self.cnv = Canvas(wdw, width=self.dim,\ 
      height=self.dim, bg='white') 
     self.cnv.grid(row=0, column=0, columnspan=2) 
     self.bt0 = Button(wdw, text='start',\ 
      command=self.start) 
     self.bt0.grid(row=1, column=0, sticky=W+E) 
     self.bt1 = Button(wdw, text='stop',\ 
      command=self.stop) 
     self.bt1.grid(row=1, column=1, sticky=W+E) 

    def map2table(self, pnt): 
     """ 
     Keeps the ball on the canvas table. 
     """ 
     if pnt < 0: 
      (quo, rest) = divmod(-pnt, self.dim) 
     else: 
      (quo, rest) = divmod(pnt, self.dim) 
     return rest 

    def placecoin(self, xpt, ypt): 
     self.cnv.create_oval(xpt-1, ypt-1, xpt+1, ypt+1,\ 
      width=2, outline='red', fill='red', tags='coin') 

    def drawball(self): 
     """ 
     Draws the ball on the canvas. 
     """ 
     xpt = self.map2table(self.xpt) 
     ypt = self.map2table(self.ypt) 
     self.cnv.delete('dot') 
     self.cnv.create_oval(xpt-1, ypt-1, xpt+1, ypt+1,\ 
      width=1, outline='black', fill='red', tags='dot') 

    def animate(self): 
     """ 
     Performs the animation. 
     """ 
     self.drawball() 
     val = [] 
     for k in range(400): 
      val1 = CoinToss.cointoss(3,k,self.dim//2) 
      val.append(val1) 

     points = {} 
     for i in range(1,401): 
      points[i] = 0 
     for i in range(0,400): 
      for j in range(0,400): 
       (xpt, ypt) = (self.xpt, self.ypt) 
       self.xpt = val[i][1][j] 
       # print("x %d",self.xpt) 
       self.ypt = ypt + 1 
       # print("y %d",self.ypt) 
       self.cnv.after(self.dly) 
       self.drawball() 
       self.cnv.update() 

       #Puts the coin on top each other 
       if self.ypt == 400: 
        if points[self.xpt]>=1: 
         self.placecoin(val[i][1][-1],400-points[self.xpt]) 
        else: 
         self.placecoin(val[i][1][-1],400) 
        points[self.xpt]+=3 
        self.ypt = 0 

    def start(self): 
     """ 
     Starts the animation. 
     """ 
     self.togo = True 
     self.animate() 

    def stop(self): 
     """ 
     Stops the animation. 
     """ 
     self.togo = False 

def main(): 
    """ 
    Defines the dimensions of the canvas 
    and launches the main event loop. 
    """ 
    top = Tk() 
    dimension = 400 # dimension of canvas 
    increment = 10 # increment for coordinates 
    delay = 1  # how much sleep before update 
    num_flips = 3 
    num_value = dimension//2 
    FlipBell(top, dimension, increment, delay) 
    top.mainloop() 

if __name__ == "__main__": 
    main() 

cointoss.py

from random import randint 
import random 


class CoinToss: 
    coin = 0 
    def __init__(self, value,num_flip): 
     # self.id = 1 
     self.v = value 
     self.state = 1 
     self.flip = num_flip 
     CoinToss.coin += 1 


    def cointoss(self,coin,value): 
     print('The ball at the start: ball: %d, state: %d, value: %d' % (coin, self, value)) 
     value_change = value 
     coin_change = [] 
     for i in range(1,400+1): 
      value = value_change 
      value_change = CoinToss.flip(value) 
      print('after flip %d, ball: %d, state: %d, value: %d' % (i,coin, i, value_change)) 
      coin_change.append(value_change) 
     return([coin,coin_change]) 


    def flip(self): 
     rand_value = randint(0, 1) 
     if rand_value == 1: 
      self +=1 
     else: 
      self -=1 
     return self 

回答

1

您有一個名爲兩種功能:在CoinToss變量 「翻轉」,這是令人困惑的。此外,您使用「標籤」關鍵字,它應該是「標籤」。有多種方法可以對此進行編碼。下面的代碼不是一個完整的解決方案,而是一個簡單的例子,展示瞭如何使用CoinToss類來創建和移動單個球(不檢查是否移出畫布)。 FlipBell類將每個CoinToss實例存儲在一個列表中,並在每次創建一個球時爲每個類調用「flip」函數。您也可以使用CoinToss類中的「after」來讓flip功能重複調用它自己。

from tkinter import * 
from random import randint 

class FlipBell(object): 
    """ 
    GUI to simulate cointoss. 
    """ 
    def __init__(self, wdw, dimension, delay): 
     """ 
     Determines the layout of the GUI. 
     wdw : top level widget, the main window, 
     dimension : determines the size of the canvas, 
     increment : step size for a billiard move, 
     delay : time between updates of canvas. 
     """ 
     wdw.title('Coin flips and Bell Curve') 
     self.cnv = Canvas(wdw, width=dimension, 
          height=dimension, bg='white') 
     self.cnv.grid() 

     self.ct_instances=[] 
     self.colors=["blue", "red", "yellow", "gray", "green"] 
     self.delay=delay 
     self.offset=0 
     self.create_next() 

    def create_next(self): 
     """ create one ball for each color in self.colors 
      and call each existing ball's flip function to 
      move it a random amount 
     """ 
     x=5 
     y=5 
     incr=10*self.offset 
     CT=CoinToss(self.cnv, x+incr, y+incr, self.colors[self.offset]) 
     ##save each CoinToss (ball) instance in a list 
     self.ct_instances.append(CT) 
     self.offset += 1 

     ## call flip (move ball) for each instance 
     for instance in self.ct_instances: 
      instance.flip() 

     if self.offset < len(self.colors): 
      self.cnv.after(self.delay, self.create_next) 

class CoinToss: 
    def __init__(self, canvas, start_x, start_y, color): 
     self.cnv=canvas 
     self.cointoss(start_x, start_y, color) 


    def cointoss(self, start_x, start_y, color): 
     self.this_ball=self.cnv.create_oval(start_x-5, start_y-5, start_x+5, start_y+5, 
         outline='black', fill=color, tag="dot") 

    def flip(self): 
     """ move the ball created for this class instance by a random amount 
     """ 
     rand_value = randint(10, 50) 
     self.cnv.move(self.this_ball, rand_value, rand_value) 

if __name__ == "__main__": 
    top = Tk() 
    dimension = 400 # dimension of canvas 
    delay = 500  # how much sleep before update --> 1/2 second 
    num_flips = 3 
    FP=FlipBell(top, dimension, delay) 
    top.mainloop() 
+0

謝謝你的幫助。它幫助我找出了另一種方式來做到這一點。 – Abhi