Mercurial > code > home > repos > light9
comparison Widgets/FlyingFader.py @ 9:342f7d1c7561
The FlyingFader will accept keyboard values and fade to them over 1.5
The FlyingFader will accept keyboard values and fade to them over 1.5
seconds. Combinations of control and alt change that speed. RMB
also creates a fade and LMB will cancel them. Colors are pretty
and informative. Fades can be created manually with the newfade()
function.
author | dmcc |
---|---|
date | Sun, 07 Jul 2002 05:13:12 +0000 |
parents | 45b12307c695 |
children | c65119b66b00 |
comparison
equal
deleted
inserted
replaced
8:6faae180d1c5 | 9:342f7d1c7561 |
---|---|
1 from Tix import * | 1 from Tkinter import * |
2 from time import time,sleep | 2 from time import time |
3 from __future__ import division | |
4 | |
5 class Mass: | |
6 def __init__(self): | |
7 self.x=0 # position | |
8 self.xgoal=0 # position goal | |
9 | |
10 self.v=0 # velocity | |
11 self.maxspeed = .8 # maximum speed, in position/second | |
12 self.maxaccel = 3 # maximum acceleration, in position/second^2 | |
13 self.eps = .03 # epsilon - numbers within this much are considered the same | |
14 | |
15 self._lastupdate=time() | |
16 self._stopped=1 | |
17 | |
18 def equal(self,a,b): | |
19 return abs(a-b)<self.eps | |
20 | |
21 def stop(self): | |
22 self.v=0 | |
23 self.xgoal=self.x | |
24 self._stopped=1 | |
25 | |
26 def update(self): | |
27 t0 = self._lastupdate | |
28 tnow = time() | |
29 self._lastupdate = tnow | |
30 | |
31 dt = tnow-t0 | |
32 | |
33 self.x += self.v*dt | |
34 # hitting the ends stops the slider | |
35 if self.x>1: self.v=max(self.v,0); self.x=1 | |
36 if self.x<0: self.v=min(self.v,0); self.x=0 | |
37 | |
38 if self.equal(self.x,self.xgoal): | |
39 self.x=self.xgoal # clean up value | |
40 self.stop() | |
41 return | |
42 | |
43 self._stopped=0 | |
44 dir = (-1.0,1,0)[self.xgoal>self.x] | |
45 | |
46 if abs(self.xgoal-self.x) < abs(self.v*5*dt): | |
47 # apply the brakes on the last 5 steps | |
48 dir *= -.5 | |
49 | |
50 self.v += dir*self.maxaccel*dt # velocity changes with acceleration in the right direction | |
51 self.v = min(max(self.v,-self.maxspeed),self.maxspeed) # clamp velocity | |
52 | |
53 #print "x=%+.03f v=%+.03f a=%+.03f %f" % (self.x,self.v,self.maxaccel,self.xgoal) | |
54 | |
55 def goto(self,newx): | |
56 self.xgoal=newx | |
57 | |
58 def ismoving(self): | |
59 return not self._stopped | |
60 | 3 |
61 class FlyingFader(Frame): | 4 class FlyingFader(Frame): |
62 def __init__(self, master, variable, label, fadedur=1.5, font=('Arial', 8), labelwidth=12, | 5 def __init__(self, master, variable, label, time=1.5, font=('Arial', 8), |
63 **kw): | 6 **kw): |
64 Frame.__init__(self, master) | 7 Frame.__init__(self, master) |
65 self.name = label | 8 self.name = label |
66 self.variable = variable | 9 self.variable = variable |
10 self.fadelength = time | |
11 self.curfade = None | |
12 self.fadetimes = 0, 0 | |
67 | 13 |
68 self.mass = Mass() | |
69 | |
70 self.config({'bd':1, 'relief':'raised'}) | 14 self.config({'bd':1, 'relief':'raised'}) |
71 scaleopts = {'variable' : variable, 'showvalue' : 0, 'from' : 1.0, | 15 self.scale = Scale(self, variable=variable, showvalue=0, from_=100, |
72 'to' : 0, 'res' : 0.001, 'width' : 20, 'length' : 200, 'orient':'vert'} | 16 to_=0, res=0.1, width=20, length=200) |
73 scaleopts.update(kw) | 17 self.vlabel = Label(self, text="0.0", font=font) |
74 if scaleopts['orient']=='vert': | 18 self.label = Label(self, text=label, wraplength=40, font=font) |
75 side1=TOP | |
76 side2=BOTTOM | |
77 else: | |
78 side1=RIGHT | |
79 side2=LEFT | |
80 | |
81 self.scale = Scale(self, **scaleopts) | |
82 self.vlabel = Label(self, text="0.0", width=6, font=font) | |
83 self.label = Label(self, text=label, font=font, anchor='w',width=labelwidth) #wraplength=40, ) | |
84 | 19 |
85 self.oldtrough = self.scale['troughcolor'] | 20 self.oldtrough = self.scale['troughcolor'] |
86 | 21 |
87 self.scale.pack(side=side2, expand=1, fill=BOTH, anchor='c') | 22 self.scale.pack(side=TOP, expand=1, fill=BOTH, anchor='c') |
88 self.vlabel.pack(side=side2, expand=0, fill=X) | 23 self.vlabel.pack(side=BOTTOM, expand=0, fill=X) |
89 self.label.pack(side=side2, expand=0, fill=X) | 24 self.label.pack(side=BOTTOM, expand=0, fill=X) |
90 | 25 |
91 for k in range(1, 10): | 26 for k in range(1, 10): |
92 self.scale.bind("<Key-%d>" % k, | 27 self.scale.bind("<Key-%d>" % k, |
93 lambda evt, k=k: self.newfade(k / 10.0, evt)) | 28 lambda evt, k=k: self.newfade(k * 10, evt)) |
94 | 29 |
95 self.scale.bind("<Key-0>", lambda evt: self.newfade(1.0, evt)) | 30 self.scale.bind("<Key-0>", lambda evt: self.newfade(100, evt)) |
96 self.scale.bind("<grave>", lambda evt: self.newfade(0, evt)) | 31 self.scale.bind("<grave>", lambda evt: self.newfade(0, evt)) |
97 | 32 |
98 self.scale.bind("<1>", self.cancelfade) | 33 self.scale.bind("<1>", self.cancelfade) |
99 self.scale.bind("<2>", self.cancelfade) | |
100 self.scale.bind("<3>", self.mousefade) | 34 self.scale.bind("<3>", self.mousefade) |
101 | 35 |
102 self.trace_ret = self.variable.trace('w', self.updatelabel) | 36 self.variable.trace('w', self.updatelabel) |
103 self.bind("<Destroy>",self.ondestroy) | |
104 | |
105 def ondestroy(self,*ev): | |
106 self.variable.trace_vdelete('w',self.trace_ret) | |
107 | 37 |
108 def cancelfade(self, evt): | 38 def cancelfade(self, evt): |
109 self.fadegoal = self.variable.get() | 39 self.fadetimes = 0, 0 |
110 self.fadevel = self.fadeacc = 0 | 40 self.curfade = 0, self.variable.get() |
111 | |
112 self.scale['troughcolor'] = self.oldtrough | 41 self.scale['troughcolor'] = self.oldtrough |
113 | 42 |
114 def mousefade(self, evt): | 43 def mousefade(self, evt): |
115 target = float(self.tk.call(self.scale, 'get', evt.x, evt.y)) | 44 target = float(self.tk.call(self.scale, 'get', evt.x, evt.y)) |
116 self.newfade(target, evt) | 45 self.newfade(target, evt) |
117 | 46 |
118 def ismoving(self): | 47 def newfade(self, newlevel, evt=None, length=None): |
119 return self.fadevel!=0 or self.fadeacc!=0 | 48 if length is None: |
49 length = self.fadelength | |
50 mult = 1 | |
120 | 51 |
121 def newfade(self, newlevel, evt=None, length=None): | |
122 | |
123 # these are currently unused-- Mass needs to accept a speed input | |
124 mult = 1 | |
125 if evt.state & 8 and evt.state & 4: mult = 0.25 # both | 52 if evt.state & 8 and evt.state & 4: mult = 0.25 # both |
126 elif evt.state & 8: mult = 0.5 # alt | 53 elif evt.state & 8: mult = 0.5 # alt |
127 elif evt.state & 4: mult = 2 # control | 54 elif evt.state & 4: mult = 2 # control |
128 | 55 |
56 now = time() | |
57 self.fadetimes = (now, now + (mult * length)) | |
58 self.curfade = (self.variable.get(), newlevel) | |
129 | 59 |
130 self.mass.x = self.variable.get() | 60 self.scale['troughcolor'] = 'red' |
131 self.mass.goto(newlevel) | |
132 | 61 |
133 self.gofade() | 62 self.gofade() |
134 | 63 |
135 def gofade(self): | 64 def gofade(self): |
136 self.mass.update() | 65 now = time() |
137 self.variable.set(self.mass.x) | 66 start, end = self.fadetimes |
138 | 67 lstart, lend = self.curfade |
139 if not self.mass.ismoving(): | 68 if now > end: |
69 self.fadetimes = 0, 0 | |
70 self.variable.set(lend) | |
140 self.scale['troughcolor'] = self.oldtrough | 71 self.scale['troughcolor'] = self.oldtrough |
141 return | 72 return |
142 | 73 percent = (now - start) / (end - start) |
143 # blink the trough while the thing's moving | 74 newvalue = (percent * (lend - lstart)) + lstart |
144 if time()%.4>.2: | 75 self.variable.set(newvalue) |
145 # self.scale.config(troughcolor=self.oldtrough) | 76 colortrough(self.scale, percent) |
146 self.scale.config(troughcolor='orange') | 77 self.after(10, self.gofade) |
147 else: | |
148 # self.scale.config(troughcolor='white') | |
149 self.scale.config(troughcolor='yellow') | |
150 | |
151 # colorfade(self.scale, percent) | |
152 self.after(30, self.gofade) | |
153 | 78 |
154 def updatelabel(self, *args): | 79 def updatelabel(self, *args): |
155 if self.variable: | 80 self.vlabel['text'] = "%.1f" % self.variable.get() |
156 self.vlabel['text'] = "%.3f" % self.variable.get() | 81 if self.fadetimes[1] == 0: # no fade |
157 # if self.fadetimes[1] == 0: # no fade | 82 self.vlabel['fg'] = 'black' |
158 # self.vlabel['fg'] = 'black' | 83 elif self.curfade[1] > self.curfade[0]: |
159 # elif self.curfade[1] > self.curfade[0]: | 84 self.vlabel['fg'] = 'red' |
160 # self.vlabel['fg'] = 'red' | 85 else: |
161 # else: | 86 self.vlabel['fg'] = 'blue' |
162 # self.vlabel['fg'] = 'blue' | |
163 | 87 |
164 def get(self): | |
165 return self.scale.get() | |
166 | 88 |
167 def set(self, val): | 89 def colortrough(scale, lev): |
168 self.scale.set(val) | |
169 | |
170 def colorfade(scale, lev): | |
171 low = (255, 255, 255) | 90 low = (255, 255, 255) |
172 high = (0, 0, 0) | 91 high = (0, 0, 0) |
173 out = [int(l+lev*(h-l)) for h, l in zip(high,low)] | 92 out = [int(l+lev*(h-l)) for h,l in zip(high,low)] |
174 col="#%02X%02X%02X" % tuple(out) | 93 col="#%02X%02X%02X" % tuple(out) |
175 scale.config(troughcolor=col) | 94 scale.config(troughcolor=col) |
176 | 95 |
177 if __name__ == '__main__': | 96 if __name__ == '__main__': |
178 root = Tk() | 97 root = Tk() |