[Interest] To a truly smooth progress bar (QML)

Jason H jhihn at gmx.com
Wed Apr 13 16:09:51 CEST 2016

I am trying to come up with a very smooth yet accurate progress bar. My code for the 1 second update interval use case is down below.

The use case of this bar is that there is a regular interval that the value is updated, either from a timer, or a consistent CPU-bound process. Another example would be a seek bar from the video player which updates it's position every second. To this end, I try to control the size change through velocity. The SmoothedAnimation though uses a InOutQuad, and not Linear for eading. Changing it to Linear helps, but I've never been able to get it to smoothly continue past an update boundary. I've tried various smoothing techniques (like Exponential moving average) to try to smooth this out, but It's never perfect, and im post cases makes it worse. Can I get it to be perfect? I don't care so much that the bar is absolutely numerically accurate, it can be a few pixels off, but it shouldn't be wildly inaccurate.


import QtQuick 2.0

Rectangle {
	property real percent: 0
	property color  barColor: "white"
	property real lastUpdateTime: -1
	property real lastUpdateValue: 0
	property alias smooth: smoothBehavior.enabled
	property alias velocity: numAnim.velocity
		smoothBehavior.enabled = lastUpdateValue < percent
		if (!smoothBehavior.enabled)

	Rectangle {
		color: barColor
		height: parent.height
		width: parent.width * percent
		antialiasing: true

	Behavior on percent {
		id: smoothBehavior
		onEnabledChanged: console.debug("smoothBehavior", enabled)

		SmoothedAnimation {
			id: numAnim
			easing.type: Easing.Linear
			duration:1050 //average of just less than 1 update per second, ~1060ms.
			reversingMode: SmoothedAnimation.Sync

== the code for updating the velocity dynamically == 
ProgressBar {
	property real lastUpdateTime: -1
	property real lastUpdateValue: 0
	onPercentChanged: {
		var now = new Date().getTime()/1000;
		if (lastUpdateTime != -1) {
			var dt = now - lastUpdateTime;
			var dv = percent - lastUpdateValue ;
			var v = dv / dt ;
			console.log(percent, "velocity (pps):", v*width, "d%:", dv, "dt:", dt, "w:", width,  "%/s:", v)
			if (v > 0) {
				velocity = v*width;
			} else if (v < 0) {
				velocity = 1000000 //reversingMode: Sync doesn't seem to work?
		lastUpdateTime = now;
		lastUpdateValue = percent;

More information about the Interest mailing list