Changeset - 342f7d1c7561
[Not reviewed]
default
0 1 0
dmcc - 22 years ago 2002-07-07 05:13:12

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.
1 file changed with 46 insertions and 127 deletions:
0 comments (0 inline, 0 general)
Widgets/FlyingFader.py
Show inline comments
 
from Tix import *
 
from time import time,sleep
 
from __future__ import division
 

	
 
class Mass:
 
    def __init__(self):
 
        self.x=0 # position
 
        self.xgoal=0 # position goal
 
        
 
        self.v=0 # velocity
 
        self.maxspeed = .8 # maximum speed, in position/second
 
        self.maxaccel = 3 # maximum acceleration, in position/second^2
 
        self.eps = .03 # epsilon - numbers within this much are considered the same
 

	
 
        self._lastupdate=time()
 
        self._stopped=1
 

	
 
    def equal(self,a,b):
 
        return abs(a-b)<self.eps
 

	
 
    def stop(self):
 
        self.v=0
 
        self.xgoal=self.x
 
        self._stopped=1
 
        
 
    def update(self):
 
        t0 = self._lastupdate
 
        tnow = time()
 
        self._lastupdate = tnow
 

	
 
        dt = tnow-t0
 

	
 
        self.x += self.v*dt
 
        # hitting the ends stops the slider
 
        if self.x>1: self.v=max(self.v,0); self.x=1
 
        if self.x<0: self.v=min(self.v,0); self.x=0
 
            
 
        if self.equal(self.x,self.xgoal):
 
            self.x=self.xgoal # clean up value
 
            self.stop()
 
            return
 
        
 
        self._stopped=0
 
        dir = (-1.0,1,0)[self.xgoal>self.x]
 

	
 
        if abs(self.xgoal-self.x) < abs(self.v*5*dt):
 
            # apply the brakes on the last 5 steps
 
            dir *= -.5
 

	
 
        self.v += dir*self.maxaccel*dt # velocity changes with acceleration in the right direction
 
        self.v = min(max(self.v,-self.maxspeed),self.maxspeed) # clamp velocity
 

	
 
        #print "x=%+.03f v=%+.03f a=%+.03f %f" % (self.x,self.v,self.maxaccel,self.xgoal)
 

	
 
    def goto(self,newx):
 
        self.xgoal=newx
 

	
 
    def ismoving(self):
 
        return not self._stopped
 
from Tkinter import *
 
from time import time
 

	
 
class FlyingFader(Frame):
 
    def __init__(self, master, variable, label, fadedur=1.5, font=('Arial', 8), labelwidth=12,
 
    def __init__(self, master, variable, label, time=1.5, font=('Arial', 8), 
 
                 **kw):
 
        Frame.__init__(self, master)
 
        self.name = label
 
        self.variable = variable
 
        self.fadelength = time
 
        self.curfade = None
 
        self.fadetimes = 0, 0
 

	
 
        self.mass = Mass()
 
        
 
        self.config({'bd':1, 'relief':'raised'})
 
        scaleopts = {'variable' : variable, 'showvalue' : 0, 'from' : 1.0,
 
                     'to' : 0, 'res' : 0.001, 'width' : 20, 'length' : 200, 'orient':'vert'}
 
        scaleopts.update(kw)
 
        if scaleopts['orient']=='vert':
 
            side1=TOP
 
            side2=BOTTOM
 
        else:
 
            side1=RIGHT
 
            side2=LEFT
 
        
 
        self.scale = Scale(self, **scaleopts)
 
        self.vlabel = Label(self, text="0.0", width=6, font=font)
 
        self.label = Label(self, text=label, font=font, anchor='w',width=labelwidth) #wraplength=40, )
 
        self.scale = Scale(self, variable=variable, showvalue=0, from_=100, 
 
            to_=0, res=0.1, width=20, length=200)
 
        self.vlabel = Label(self, text="0.0", font=font)
 
        self.label = Label(self, text=label, wraplength=40, font=font)
 

	
 
        self.oldtrough = self.scale['troughcolor']
 

	
 
        self.scale.pack(side=side2, expand=1, fill=BOTH, anchor='c')
 
        self.vlabel.pack(side=side2, expand=0, fill=X)
 
        self.label.pack(side=side2, expand=0, fill=X)
 
        self.scale.pack(side=TOP, expand=1, fill=BOTH, anchor='c')
 
        self.vlabel.pack(side=BOTTOM, expand=0, fill=X)
 
        self.label.pack(side=BOTTOM, expand=0, fill=X)
 

	
 
        for k in range(1, 10):
 
            self.scale.bind("<Key-%d>" % k, 
 
                lambda evt, k=k: self.newfade(k / 10.0, evt))
 
                lambda evt, k=k: self.newfade(k * 10, evt))
 

	
 
        self.scale.bind("<Key-0>", lambda evt: self.newfade(1.0, evt))
 
        self.scale.bind("<Key-0>", lambda evt: self.newfade(100, evt))
 
        self.scale.bind("<grave>", lambda evt: self.newfade(0, evt))
 

	
 
        self.scale.bind("<1>", self.cancelfade)
 
        self.scale.bind("<2>", self.cancelfade)
 
        self.scale.bind("<3>", self.mousefade)
 

	
 
        self.trace_ret = self.variable.trace('w', self.updatelabel)
 
        self.bind("<Destroy>",self.ondestroy)
 

	
 
    def ondestroy(self,*ev):
 
        self.variable.trace_vdelete('w',self.trace_ret)
 
        self.variable.trace('w', self.updatelabel)
 

	
 
    def cancelfade(self, evt):
 
        self.fadegoal = self.variable.get()
 
        self.fadevel = self.fadeacc = 0
 

	
 
        self.fadetimes = 0, 0
 
        self.curfade = 0, self.variable.get()
 
        self.scale['troughcolor'] = self.oldtrough
 

	
 
    def mousefade(self, evt):
 
        target = float(self.tk.call(self.scale, 'get', evt.x, evt.y))
 
        self.newfade(target, evt)
 

	
 
    def ismoving(self):
 
        return self.fadevel!=0 or self.fadeacc!=0
 
    def newfade(self, newlevel, evt=None, length=None):
 
        if length is None:
 
            length = self.fadelength
 
        mult = 1
 

	
 
    def newfade(self, newlevel, evt=None, length=None):
 

	
 
        # these are currently unused-- Mass needs to accept a speed input
 
        mult = 1
 
        if evt.state & 8 and evt.state & 4: mult = 0.25 # both
 
        elif evt.state & 8: mult = 0.5 # alt
 
        elif evt.state & 4: mult = 2   # control
 

	
 
        now = time()
 
        self.fadetimes = (now, now + (mult * length))
 
        self.curfade = (self.variable.get(), newlevel)
 

	
 
        self.mass.x = self.variable.get()
 
        self.mass.goto(newlevel)
 
        self.scale['troughcolor'] = 'red'
 

	
 
        self.gofade()
 

	
 
    def gofade(self):
 
        self.mass.update()
 
        self.variable.set(self.mass.x)
 

	
 
        if not self.mass.ismoving():
 
        now = time()
 
        start, end = self.fadetimes
 
        lstart, lend = self.curfade
 
        if now > end: 
 
            self.fadetimes = 0, 0
 
            self.variable.set(lend)
 
            self.scale['troughcolor'] = self.oldtrough
 
            return
 
        
 
        # blink the trough while the thing's moving
 
        if time()%.4>.2:
 
            # self.scale.config(troughcolor=self.oldtrough)
 
            self.scale.config(troughcolor='orange')
 
        else:
 
            # self.scale.config(troughcolor='white')
 
            self.scale.config(troughcolor='yellow')
 

	
 
#        colorfade(self.scale, percent)
 
        self.after(30, self.gofade)
 
        percent = (now - start) / (end - start)
 
        newvalue = (percent * (lend - lstart)) + lstart
 
        self.variable.set(newvalue)
 
        colortrough(self.scale, percent)
 
        self.after(10, self.gofade)
 

	
 
    def updatelabel(self, *args):
 
        if self.variable:
 
            self.vlabel['text'] = "%.3f" % self.variable.get()
 
#        if self.fadetimes[1] == 0: # no fade
 
#            self.vlabel['fg'] = 'black'
 
#        elif self.curfade[1] > self.curfade[0]:
 
#            self.vlabel['fg'] = 'red'
 
#        else:
 
#            self.vlabel['fg'] = 'blue'
 
        self.vlabel['text'] = "%.1f" % self.variable.get()
 
        if self.fadetimes[1] == 0: # no fade
 
            self.vlabel['fg'] = 'black'
 
        elif self.curfade[1] > self.curfade[0]:
 
            self.vlabel['fg'] = 'red'
 
        else:
 
            self.vlabel['fg'] = 'blue'
 

	
 
    def get(self):
 
        return self.scale.get()
 

	
 
    def set(self, val):
 
        self.scale.set(val)
 

	
 
def colorfade(scale, lev):
 
def colortrough(scale, lev):
 
    low = (255, 255, 255)
 
    high = (0, 0, 0)
 
    out = [int(l+lev*(h-l)) for h, l in zip(high,low)]
 
    out = [int(l+lev*(h-l)) for h,l in zip(high,low)]
 
    col="#%02X%02X%02X" % tuple(out)
 
    scale.config(troughcolor=col)
 

	
 
if __name__ == '__main__':
 
    root = Tk()
 
    root.tk_focusFollowsMouse()
0 comments (0 inline, 0 general)