Briefly update label color on value change

I have some simple numerical text labels in Perspective that will update every so often using a tag binding. I'd like them to briefly turn green and fade back to black / neutral if the number increases during a change, and similarly turn red if the number decreases. I know I can accomplish this animation using an animated style class (example screenshot below) with the infinite box unchecked for the fading effect.

But I'm trying to figure out a way to dynamically update the style class binding of the label to "activate" each time there is a change in value. This is pretty easy if the label increases and then decreases in a constant up-and-down pattern -- I'd simply update the binding to the appropriate style class using an OnChange event script. But if it increases twice in a row, it will only turn green and fade to neutral the first time. I have to change the style class to some 3rd value as an 'in between' state. This presents challenges when it comes to timing and CPU load.

Any good ideas on an easy way to make this happen? I can provide more screenshots if any of the above isn't clear.

I was able to manage this with a change script which made use of system.util.invokeAsynchronous:

def valueChanged(self, previousValue, currentValue, origin, missedEvents):
	def reset():
		from time import sleep
		sleep(1)
		self.props.textStyle.classes = ""
	if previousValue:  # null check
		self.props.textStyle.classes = "Experimentation/Increase" if currentValue.value > previousValue.value else "Experimentation/Decrease"
	system.util.invokeAsynchronous(reset)

Thank you for the answer! Are there any concerns with using sleep? I might have a hundred values on the screen utilizing this logic...

1 Like

Yes, there are.

That function to be invoked asynchronously will run on its own thread. If you have hundreds of change scripts performing this same step you're going to tie up many threads (albeit for relatively short periods of time).

Unfortunately, for what you're asking, I don't see a better way. By your own description you need this to happen every time the value changes. The only way to "trigger" the animation is to apply the style, which means it can't already be in place, which means we need to have removed it. I think this is the best solution for a questionable UI choice; transient UI on such a micro scale seems like a bad design decision.

You could mitigate the "thundering herd" problem if you set up a single-threaded executor service to run these at a designated future time. At worst, some of the attributes might not clear before the next value arrives, but you won't crush your gateway.