Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries. Thanks for all your past and future contributions.

Creating a spinnable disc with QML

From Wiki
Jump to: navigation, search
Featured Article
09 Jan
Article Metadata
Tested with
Devices(s): E7, N8, N900
Platform(s): Symbian
Keywords: QML, mouse events
Created: kratsan (28 Dec 2010)
Last edited: kiran10182 (31 Oct 2013)



This snippet shows how to create spinnable disc with QML. The rotating of the disc is implemented manually with Timer element in order to have better control of the rotation. The timer rotates the disc on the onTriggered handler using property currentSpeed. The currentSpeed will slowly approach to property targetSpeed.


MouseArea is used to provide scratching ability to the disc. The interaction is divided into three handlers, onPressed, onPositionChanged and onReleased. On the onPressed handler the place of the press is inspected, if the press hits on the corners of the disc, the mouse event is discarded. This also prevents the onReleased event to be triggered. If the mouse event hits on the disc we store the coordinates of the press and the time when the press occurred. The timer is stopped for rotating the disc - after all we have a mouse (or a finger) on top of the disc and we don't want it to turn. On the onPositionChanged handler the position of the mouse is again inspected, the angle of the previous mouse coordinate and the disc center (AC) and the current mouse coordinate and the disc center (CB) is calculated. The disc is then rotated by adding this angle to the current rotation. The current speed of the disc is set by calculating the angular speed of the disc. Finally when the onReleased event is triggered the timer is resumed and the disc will be rotated by using current speed towards to the target speed.

This technique was used in the Nokia Developer example Dj Turntable to create spinning turntable with touch interaction.


  • Qt 4.7 or higher is installed on your platform.


import Qt 4.7
Rectangle {
width: 640; height: 480
color: "black"
Rectangle {
id: disk
property real targetSpeed: 1.0
property real currentSpeed: 0
width: Math.min(parent.width, parent.height) * 0.85; height: width
radius: width / 2; color: "gray"
anchors.centerIn: parent
Text {
anchors.centerIn: parent
text: "Scratch me"
font { bold: true; pixelSize: parent.width / 10 }
color: "white"
Timer {
id: playTimer
interval: 16 // 60 fps
repeat: true
running: true
onTriggered: {
disk.rotation = (disk.rotation + 0.36 * disk.currentSpeed * interval) % 360
if(Math.abs(disk.currentSpeed - disk.targetSpeed) <= 0.01) {
disk.currentSpeed = disk.targetSpeed
else {
disk.currentSpeed += (disk.targetSpeed - disk.currentSpeed) * 0.01
MouseArea {
// Don't place this as child of disk because the
// coordination will change when disk is rotated
property real centerx: width / 2
property real centery: height / 2
property int previousX: 0
property int previousY: 0
property variant previousTime
anchors.fill: disk
onPressed: {
var xlength = Math.abs(mouse.x - centerx)
var ylength = Math.abs(mouse.y - centery)
if(Math.sqrt(xlength * xlength + ylength * ylength) > centerx) {
// The mouse press did not hit on the disk, the disk is actually
// rectangle shaped and the mouse was pressed one of the corners
mouse.accepted = false
disk.currentSpeed = 0.0
previousX = mouse.x
previousY = mouse.y
previousTime = new Date().getTime()
onReleased: playTimer.start()
onPositionChanged: {
var now = new Date().getTime()
var ax = mouse.x - centerx
var ay = centery - mouse.y
var bx = previousX - centerx
var by = centery - previousY
var angledelta = (Math.atan2(by, bx) - Math.atan2(ay, ax)) * 57.2957795
if(angledelta > 180) { angledelta -= 360 }
else if(angledelta < -180) { angledelta += 360 }
disk.rotation = (disk.rotation + angledelta) % 360
if(now - previousTime > 0) { disk.currentSpeed = angledelta * 2.77778 / (now - previousTime) }
previousX = mouse.x
previousY = mouse.y
previousTime = now
TextEdit {
anchors { bottom: disk.bottom; right: disk.right; bottomMargin: 10 }
text: "Clicks here\nare discarded"
readOnly: true
font.pixelSize: disk.width / 30
color: "white"


The snippet demonstrated implementing of a rotating disc with a ability to be scratched with mouse or finger.

This page was last modified on 31 October 2013, at 19:57.
75 page views in the last 30 days.