BlackBerry’s Cascades framework allows developers to add a lot of functionality in QML that would otherwise have to be created in C++. The platform is missing one important component however: a timer! Timers are especially useful when you need to create a workaround in your QML to make life easier. Need to defer a view calculation for just a moment later? Want to wait for layout changes in your app to finish, but aren’t exposed to the necessary signals? Right now, there’re only two options:
- Import the
QTimer
class. Unfortunately, this will break Momentics’ QML previewer. - Call a C++ function, which waits for a
QTimer
, and then triggers a QML callback that you created. What a pain!
I’ve constructed a simple workaround made entirely from QML that won’t break the Momentics previewer, but is still easy to maintain and extend.
The trick is simple:
- Piggy back off of the built-in animations framework to provide the needed timing functionality. Use an animation to change the opacity of a control that is not visible to the user.
- Allow the timer owner to set the duration and start the animation countdown without needing to know anything about how time is kept.
- Expose a signal that will be emitted when the animation is finished.
I’ve created a sample app on GitHub demonstrating the whole thing working together. The meat of the code is also included below. I hope this will help you keep more of your UI code in QML where it belongs.
// QmlTimer.qml import bb.cascades 1.0 Container { id: root opacity: 0.0 property int duration: 0 property bool timerActive: false signal triggered function startTimer() { if (duration == 0) { console.log("timer can't start when duration is 0"); return; } if (timerActive == true) { console.log("timer is already active, not starting"); return; } opacity = 0; timerActive = true; timerAnimation.play(); } function stopTimer() { timerActive = false; timerAnimation.stop(); } animations: [ FadeTransition { id: timerAnimation fromOpacity: 0 toOpacity: 1 duration: root.duration } ] onOpacityChanged: { if (timerActive == true && opacity == 1) { timerActive = false; root.triggered(); } } }