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()