summaryrefslogtreecommitdiffstats
path: root/Demo/tkinter/guido/brownian.py
blob: b08a9561cb42596b28c2e626d3cead63f3ece713 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# Brownian motion -- an example of a multi-threaded Tkinter program.

from Tkinter import *
import random
import threading
import time
import sys

WIDTH = 400
HEIGHT = 300
SIGMA = 10
BUZZ = 2
RADIUS = 2
LAMBDA = 10
FILL = 'red'

stop = 0                                # Set when main loop exits

lock = threading.Lock()                 # Protects the random generator

def particle(canvas):
    r = RADIUS
    lock.acquire()
    try:
        x = random.gauss(WIDTH/2.0, SIGMA)
        y = random.gauss(HEIGHT/2.0, SIGMA)
    finally:
        lock.release()
    p = canvas.create_oval(x-r, y-r, x+r, y+r, fill=FILL)
    while not stop:
        lock.acquire()
        try:
            dx = random.gauss(0, BUZZ)
            dy = random.gauss(0, BUZZ)
            dt = random.expovariate(LAMBDA)
        finally:
            lock.release()
        try:
            canvas.move(p, dx, dy)
        except TclError:
            break
        time.sleep(dt)

def main():
    global stop
    root = Tk()
    canvas = Canvas(root, width=WIDTH, height=HEIGHT)
    canvas.pack(fill='both', expand=1)
    np = 30
    if sys.argv[1:]:
        np = int(sys.argv[1])
    for i in range(np):
        t = threading.Thread(target=particle, args=(canvas,))
        t.start()
    try:
        root.mainloop()
    finally:
        stop = 1

main()