1- #!/usr/bin/python3
2-
1+ from __future__ import print_function
2+ import tkinter
3+ import random
4+ import string
35import sys
4- import time
56import threading
6- import random
7- import tkinter
7+ import time
88
99import unittest
1010class TestThreads (unittest .TestCase ):
@@ -31,103 +31,46 @@ def test_threads(self):
3131
3232running = True
3333
34- class Track (threading .Thread ):
35- """
36- Calculates coordinates for a ballistic track
37- with random angle and velocity
38- and fires the callback to draw each consecutive segment.
39- """
40- def __init__ (self , track_number , draw_callback ):
41- """
42- :param track_number: ordinal
43- :param draw_callback: fn(track_number, x, y)
44- that draws the extention of the specified track
45- to the specified point. The callback must keep track
46- of any previous coordinates itself.
47- """
48- threading .Thread .__init__ (self )
49- #self.setDaemon(True)
50- self .track_number = track_number
51- self .draw_callback = draw_callback
52-
34+ class EventThread (threading .Thread ):
35+ def __init__ (self ,target ):
36+ super (EventThread ,self ).__init__ ()
37+ self .target = target
5338 def run (self ):
54- #starting point for the track
55- y = 0.0001 #height
56- x = 999.0 #range
57- #initial velocities
58- yVel = 400. + random .random () * 200.
59- xVel = - 200. - random .random () * 150.
60- # Stop drawing when the track hits the ground
61- while y > 0 and running :
62- #How long to sleep, in seconds, between track updates
63- time .sleep (0.01 ) #realism: >1 Fun: 0.01
64-
65- yVel -= 9.8 #gravity, more or less
66- xVel *= .9998 #air resistance
67-
68- y += yVel
69- x += xVel
70-
71- if running :
72- self .draw_callback (self .track_number , x , y )
39+ while running :
40+ time .sleep (0.02 )
41+ c = random .choice (string .ascii_letters )
42+ self .target .event_generate (c )
7343
44+ class Main (object ):
45+ def __init__ (self ):
46+ self .root = tkinter .Tk ()
47+ self .root .bind ('<Key>' ,dummy_handler )
48+ self .threads = []
7449
75- class App :
76- """
77- The main app logic
78- """
79- def __init__ (self , window ):
80- self .track_no = 0 #last index of track added
81- self .track_coordinates = {} #coords of track tips
82- self .threads = []
50+ self .t_cleanup = threading .Thread (target = self .tf_stop )
8351
84- self .window = window
85- self .frame = tkinter .Frame (window )
86- self .frame .pack ()
87- self .graph = tkinter .Canvas (self .frame )
88- self .graph .pack ()
89-
90- self .t_cleanup = threading .Thread (target = self .tf_cleanup )
91- self .window .after (0 , self .add_tracks , 5 )
92- self .window .after (1000 , self .t_cleanup .start )
93-
94- def add_tracks (self ,depth ):
95- if depth > 0 : self .window .after (5 , self .add_tracks , depth - 1 )
96- tracks_to_add = 40
97- start_no = self .track_no
98- self .track_no += tracks_to_add
99- for self .track_no in range (start_no , self .track_no ):
100- #self.window.after(t, self.add_tracks)
101- #self.track_no += 1 #Make a new track number
102- #if (self.track_no > 40):
103- t = Track (self .track_no , self .draw_track_segment )
104- self .threads .append (t )
105- t .start ()
106-
107- def tf_cleanup (self ):
52+ def go (self ):
53+ self .root .after (0 ,self .add_threads )
54+ self .root .after (500 ,self .stop )
55+ self .root .protocol ("WM_DELETE_WINDOW" ,self .stop )
56+ self .root .mainloop ()
57+ self .t_cleanup .join ()
58+ def stop (self ):
59+ self .t_cleanup .start ()
60+ def tf_stop (self ):
10861 global running
10962 running = False
11063 for t in self .threads : t .join ()
111- self .window .after (0 ,self .window .destroy )
64+ self .root .after (0 ,self .root .destroy )
65+ def add_threads (self ):
66+ for _ in range (20 ):
67+ t = EventThread (self .root )
68+ self .threads .append (t )
69+ t .start ()
11270
113- def draw_track_segment (self , track_no , x , y ):
114- # x & y are virtual coordinates for the purpose of simulation.
115- #To convert them to screen coordinates,
116- # we scale them down so the graphs fit into the window, and move the origin.
117- # Y is also inverted because in canvas, the UL corner is the origin.
118- newsx , newsy = (250. + x / 100. , 150. - y / 100. )
71+ def dummy_handler (event ):
72+ pass
11973
120- try :
121- (oldsx , oldsy ) = self .track_coordinates [track_no ]
122- except KeyError :
123- pass
124- else :
125- self .graph .create_line (oldsx , oldsy ,
126- newsx , newsy )
127- self .track_coordinates [track_no ] = (newsx , newsy )
128-
129- def go (self ):
130- self .window .mainloop ()
13174
13275tests_gui = (TestThreads ,)
13376
@@ -138,7 +81,7 @@ def go(self):
13881 import ctypes
13982 #the bug causes crashes
14083 ctypes .windll .kernel32 .SetErrorMode (3 )
141- App ( tkinter . Tk () ).go ()
84+ Main ( ).go ()
14285 else :
14386 from test .support import run_unittest
14487 run_unittest (* tests_gui )
0 commit comments