×
Namespaces

Variants
Actions
Revision as of 04:06, 29 June 2012 by hamishwillee (Talk | contribs)

Creating a spinnable disc with QML

From Nokia Developer Wiki
Jump to: navigation, search
Featured Article
09 Jan
2011
Article Metadata
Tested with
Devices(s): E7, N8, N900
Compatibility
Platform(s): Symbian
Maemo
Symbian
Article
Keywords: QML, mouse events
Created: kratsan (28 Dec 2010)
Last edited: hamishwillee (29 Jun 2012)

Contents

Overview

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.

CreatingspinnablediscwithQMLDisc.png

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.

Preconditions

  • Qt 4.7 or higher is installed on your platform.

Sources

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
return
}
 
playTimer.stop()
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"
}
}

Postconditions

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

220 page views in the last 30 days.
×