Update multiple oval coordinates on canvas in python using tkinter -
i working on gui animate coin flips 1 @ time continuously. have 2 classes cointoss.py , flipbell.py.
cointoss class generates value change coins , flipbell used animate process.
as if have code working animate 1 coin @ time not coins @ time.
when coins logic: first 1 coin comes down according value change, next 1 comes down first coin value gets updated accordingly , on.
i need how move forward have tried far. have used loops animate process , thinking of using recursive method have logic part.
any existing code or ideas move forward great.
flipbell.py
from tkinter import tk, canvas, button, w, e import random math import pi, sin, cos cointoss import * class flipbell(object): """ gui simulate cointoss. """ def __init__(self, wdw, dimension, increment, delay): """ determines layout of gui. wdw : top level widget, main window, dimension : determines size of canvas, increment : step size billiard move, delay : time between updates of canvas. """ wdw.title('coin flips , bell curve') self.dim = dimension # dimension of canvas self.inc = increment self.dly = delay self.togo = false # state of animation # initial coordinates of 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 ball on 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 ball on 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 animation. """ self.drawball() val = [] k in range(400): val1 = cointoss.cointoss(3,k,self.dim//2) val.append(val1) points = {} in range(1,401): points[i] = 0 in range(0,400): 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 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 animation. """ self.togo = true self.animate() def stop(self): """ stops animation. """ self.togo = false def main(): """ defines dimensions of canvas , launches main event loop. """ top = tk() dimension = 400 # dimension of canvas increment = 10 # increment coordinates delay = 1 # how 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 @ start: ball: %d, state: %d, value: %d' % (coin, self, value)) value_change = value coin_change = [] 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
you have named both function , variable "flip" in cointoss confusing. also, use "tags" keyword , should "tag". there more 1 way code this. code below not complete solution simple example shows how use cointoss class create , move individual ball (doesn't check move off of canvas). flipbell class stores each cointoss instance in list , calls "flip" function each class each time ball created. use "after" within cointoss class have flip function call repeatedly.
from tkinter import * random import randint class flipbell(object): """ gui simulate cointoss. """ def __init__(self, wdw, dimension, delay): """ determines layout of gui. wdw : top level widget, main window, dimension : determines size of canvas, increment : step size billiard move, delay : time between updates of canvas. """ wdw.title('coin flips , 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 1 ball each color in self.colors , call each existing ball's flip function move 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 list self.ct_instances.append(ct) self.offset += 1 ## call flip (move ball) each instance 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 ball created class instance 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 sleep before update --> 1/2 second num_flips = 3 fp=flipbell(top, dimension, delay) top.mainloop()
Comments
Post a Comment