Last active
July 29, 2016 03:38
-
-
Save peteristhegreat/00bbbdd045b51815935dd80ffe48f902 to your computer and use it in GitHub Desktop.
qt-quick-qml-and-canvas-tutorial pie chart example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://www.slideshare.net/emayssat/qt-quick-qml-and-canvas-tutorial | |
import QtQuick 2.0 | |
Item { | |
Rectangle { | |
id: root | |
width: 640 | |
height: 360 | |
color: "#3C3C3C" | |
ListModel { | |
id: model | |
ListElement { label:"Scientific Research"; value:21; color:"#99e600" } | |
ListElement { label:"Engineering & Design"; value:18; color:"#99cc00" } | |
ListElement { label:"Automotive"; value:14; color:"#99b300" } | |
ListElement { label:"Aerospace"; value:13; color:"#9f991a" } | |
ListElement { label:"Automation & Machine Tools"; value:13; color:"#a48033" } | |
ListElement { label:"Medical & Bioinformatics"; value:13; color:"#a9664d" } | |
ListElement { label:"Imaging & Special Effects"; value:12; color:"#ae4d66" } | |
ListElement { label:"Defense"; value:11; color:"#b33380" } | |
ListElement { label:"Test & Measurement Systems"; value:9; color:"#a64086" } | |
ListElement { label:"Oil & Gas"; value:9; color:"#994d8d" } | |
ListElement { label:"Entertainment & Broadcasting"; value:7; color:"#8d5a93" } | |
ListElement { label:"Financial"; value:6; color:"#806699" } | |
ListElement { label:"Consumer Electronics"; value:4; color:"#8073a6" } | |
ListElement { label:"Other"; value:38; color:"#8080b3" } | |
} | |
} | |
ListView { | |
id: view | |
anchors.top: parent.top | |
anchors.bottom: parent.bottom | |
anchors.left: parent.horizontalCenter | |
anchors.right: parent.right | |
anchors.margins: 16 | |
clip: true | |
focus: true | |
model: model | |
delegate: Item { | |
width: view.width | |
height: 32 | |
Rectangle { | |
anchors.fill: parent | |
anchors.margins: 1 | |
radius: 2 | |
color: model.color | |
border.color: Qt.lighter(root.color) | |
} | |
Text { | |
anchors.verticalCenter: parent.verticalCenter | |
anchors.left: parent.left | |
anchors.margins: 8 | |
text: model.label | |
color: "#1C1C1C" | |
} | |
Text { | |
anchors.verticalCenter: parent.verticalCenter | |
anchors.right: parent.right | |
anchors.margins: 8 | |
text: model.value | |
color: "#1C1C1C" | |
} | |
// handle mouse clicks | |
MouseArea { | |
anchors.fill: parent | |
onClicked: { | |
view.currentIndex = index | |
} | |
} | |
} | |
// highlight the currently selected item | |
highlight: Item { | |
z: 10 | |
width: view.currentItem.width | |
height: view.currentItem.height | |
Rectangle { | |
anchors.fill: parent | |
anchors.margins: 1 | |
radius: 2 | |
color: "transparent" | |
border.width: 3 | |
border.color: Qt.lighter(model.get(view.currentIndex).color) | |
Behavior on border.color { PropertyAnimation {} } | |
} | |
} | |
// request a repaint of the canvas whenever | |
// the currently selected item changes | |
onCurrentIndexChanged: { canvas.requestPaint() } | |
} | |
Canvas { | |
id: canvas | |
anchors.top: parent.top | |
anchors.bottom: parent.bottom | |
anchors.left: parent.left | |
anchors.right: parent.horizontalCenter | |
smooth: true | |
// animate the rotation | |
Behavior on rotation { SpringAnimation { spring: 1; damping: 0.2 } } | |
onPaint: { | |
var ctx = canvas.getContext('2d') | |
ctx.clearRect(0, 0, width, height) | |
var centerX = width / 2 | |
var centerY = height / 2 | |
var radius = 0.9 * Math.min(width, height) / 2 | |
var radiusFactor = 1.0 | |
var startAngle = 0.0 | |
var endAngle = 0.0 | |
var angleFactor = 2 * Math.PI / modelSum() | |
ctx.lineWidth = 2 | |
ctx.strokeStyle = Qt.lighter(root.color) | |
for (var index = 0; index < model.count; index++) | |
{ | |
startAngle = endAngle | |
endAngle = startAngle + model.get(index).value * angleFactor | |
// scale the currently selected piece and | |
// rotate the canvas element accordingly | |
if (index == view.currentIndex) { | |
radiusFactor = 1.02 | |
canvas.rotation = - 180 / Math.PI * (startAngle + (endAngle - startAngle) / 2) | |
} else { | |
radiusFactor = 1.0 | |
} | |
ctx.fillStyle = model.get(index).color | |
ctx.beginPath() | |
ctx.moveTo(centerX, centerY) | |
ctx.arc(centerX, centerY, radius * radiusFactor, startAngle, endAngle, false) | |
ctx.lineTo(centerX, centerY) | |
ctx.fill() | |
ctx.stroke() | |
} | |
// overlay a radial gradient | |
var gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius) | |
gradient.addColorStop(0.0, Qt.rgba(1.0, 1.0, 1.0, 0.0)) | |
gradient.addColorStop(1.0, Qt.rgba(0.0, 0.0, 0.0, 0.3)) | |
ctx.beginPath() | |
ctx.moveTo(centerX, centerY) | |
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false) | |
ctx.fillStyle = gradient | |
ctx.fill() | |
} | |
function modelSum() | |
{ | |
var modelSum = 0 | |
for (var index = 0; index < model.count; index++) | |
{ | |
modelSum += model.get(index).value | |
} | |
return modelSum | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://www.slideshare.net/emayssat/qt-quick-qml-and-canvas-tutorial | |
Canvas { | |
id: canvas | |
width: 300 | |
height: 300 // the function "draw()" can be put into the "onPaint" handler | |
onPaint: { // the acquisition of the rendering context needs to be adapted 4.2. The Qt Quick Canvas Code 20 | |
//24. Qt Quick Painting using Canvas Item, Release 1.0 | |
var ctx = canvas.getContext('2d'); | |
ctx.fillRect(0,0,300,300); | |
for (var i=0;i<3;i++) { | |
for (var j=0;j<3;j++) { | |
ctx.save(); | |
ctx.strokeStyle = "#9CFF00"; | |
ctx.translate(50+j*100,50+i*100); | |
drawSpirograph(ctx,20*(j+2)/(j+1),-8*(i+3)/(i+1),10); ctx.restore(); | |
} | |
} | |
} // the utility function "drawSpirograph()" can remain unchanged | |
function drawSpirograph(ctx,R,r,O) | |
{ | |
var x1 = R-O; | |
var y1 = 0; | |
var i = 1; | |
ctx.beginPath(); | |
ctx.moveTo(x1,y1); | |
do { | |
if (i>20000) | |
break; | |
var x2 = (R+r)*Math.cos(i*Math.PI/72) - (r+O)*Math.cos(((R+r)/r)*(i*Math.PI/72)) | |
var y2 = (R+r)*Math.sin(i*Math.PI/72) - (r+O)*Math.sin(((R+r)/r)*(i*Math.PI/72)) | |
ctx.lineTo(x2,y2); x1 = x2; y1 = y2; i++; | |
} while (x2 != R-O && y2 != 0 ); | |
ctx.stroke(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//import QtQuick 2.0 | |
import QtQuick 2.2 | |
Item { | |
id: root | |
property var color: "#3C3C3C" | |
ListModel { | |
id: model | |
ListElement { label:"Scientific Research"; value:21; color:"#99e600" } | |
ListElement { label:"Engineering & Design"; value:18; color:"#99cc00" } | |
ListElement { label:"Automotive"; value:14; color:"#99b300" } | |
ListElement { label:"Aerospace"; value:13; color:"#9f991a" } | |
ListElement { label:"Automation & Machine Tools"; value:13; color:"#a48033" } | |
ListElement { label:"Medical & Bioinformatics"; value:13; color:"#a9664d" } | |
ListElement { label:"Imaging & Special Effects"; value:12; color:"#ae4d66" } | |
ListElement { label:"Defense"; value:11; color:"#b33380" } | |
ListElement { label:"Test & Measurement Systems"; value:9; color:"#a64086" } | |
ListElement { label:"Oil & Gas"; value:9; color:"#994d8d" } | |
ListElement { label:"Entertainment & Broadcasting"; value:7; color:"#8d5a93" } | |
ListElement { label:"Financial"; value:6; color:"#806699" } | |
ListElement { label:"Consumer Electronics"; value:4; color:"#8073a6" } | |
ListElement { label:"Other"; value:38; color:"#8080b3" } | |
} | |
ListView { | |
id: view | |
anchors.top: parent.top | |
anchors.bottom: parent.bottom | |
anchors.left: parent.horizontalCenter | |
anchors.right: parent.right | |
anchors.margins: 16 | |
clip: true | |
focus: true | |
model: model | |
delegate: Item { | |
width: view.width | |
height: 32 | |
Rectangle { | |
anchors.fill: parent | |
anchors.margins: 1 | |
radius: 2 | |
color: model.color | |
border.color: Qt.lighter(root.color) | |
} | |
Text { | |
anchors.verticalCenter: parent.verticalCenter | |
anchors.left: parent.left | |
anchors.margins: 8 | |
text: model.label | |
color: "#1C1C1C" | |
} | |
Text { | |
anchors.verticalCenter: parent.verticalCenter | |
anchors.right: parent.right | |
anchors.margins: 8 | |
text: model.value | |
color: "#1C1C1C" | |
} | |
// handle mouse clicks | |
MouseArea { | |
anchors.fill: parent | |
onClicked: { | |
view.currentIndex = index | |
} | |
} | |
} | |
// highlight the currently selected item | |
highlight: Item { | |
z: 10 | |
width: view.currentItem.width | |
height: view.currentItem.height | |
Rectangle { | |
anchors.fill: parent | |
anchors.margins: 1 | |
radius: 2 | |
color: "transparent" | |
border.width: 3 | |
border.color: Qt.lighter(model.get(view.currentIndex).color) | |
Behavior on border.color { PropertyAnimation {} } | |
} | |
} | |
// request a repaint of the canvas whenever | |
// the currently selected item changes | |
onCurrentIndexChanged: { canvas.requestPaint() } | |
} | |
Canvas { | |
id: canvas | |
anchors.top: parent.top | |
anchors.bottom: parent.bottom | |
anchors.left: parent.left | |
anchors.right: parent.horizontalCenter | |
smooth: true | |
// animate the rotation | |
Behavior on rotation { | |
// SpringAnimation { | |
RotationAnimation { | |
// spring: 1; | |
// damping: 0.2 | |
easing.period: 5 | |
easing.type: Easing.InOutBack | |
duration: 3000 | |
direction: Clockwise | |
} | |
} | |
onPaint: { | |
var deg2rad = 180 / Math.PI | |
var ctx = canvas.getContext('2d') | |
ctx.clearRect(0, 0, width, height) | |
var centerX = width / 2 | |
var centerY = height / 2 | |
var radius = 0.9 * Math.min(width, height) / 2 | |
var radiusFactor = 1.0 | |
var startAngle = 0.0 | |
var endAngle = 0.0 | |
var angleFactor = 2 * Math.PI / modelSum() | |
ctx.lineWidth = 2 | |
ctx.strokeStyle = Qt.lighter(root.color) | |
for (var index = 0; index < model.count; index++) | |
{ | |
startAngle = endAngle | |
endAngle = startAngle + model.get(index).value * angleFactor | |
// scale the currently selected piece and | |
// rotate the canvas element accordingly | |
if (index == view.currentIndex) { | |
radiusFactor = 1.02 | |
canvas.rotation = - 180 / Math.PI * (startAngle + (endAngle - startAngle) / 2) | |
} else { | |
radiusFactor = 1.0 | |
} | |
ctx.fillStyle = model.get(index).color | |
ctx.beginPath() | |
ctx.moveTo(centerX, centerY) | |
ctx.arc(centerX, centerY, radius * radiusFactor, startAngle, endAngle, false) | |
ctx.lineTo(centerX, centerY) | |
ctx.fill() | |
ctx.stroke() | |
ctx.closePath() | |
var offset = (endAngle - startAngle)/2 | |
ctx.save(); | |
ctx.translate(centerX,centerY) | |
ctx.rotate((startAngle + offset))// * deg2rad) | |
ctx.textAlign = "right"; | |
ctx.fillStyle = "#000" | |
ctx.fillText(model.get(index).label, radius - 5,0);//centerX, centerY); | |
console.log(model.get(index).label, startAngle) | |
ctx.restore(); | |
// ctx.rotate(-1*(startAngle + offset))// * deg2rad) | |
// ctx.translate(-centerX, -centerY) | |
} | |
// overlay a radial gradient | |
var gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius) | |
gradient.addColorStop(0.0, Qt.rgba(1.0, 1.0, 1.0, 0.0)) | |
gradient.addColorStop(1.0, Qt.rgba(0.0, 0.0, 0.0, 0.3)) | |
ctx.beginPath() | |
ctx.moveTo(centerX, centerY) | |
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false) | |
ctx.fillStyle = gradient | |
ctx.fill() | |
} | |
function modelSum() | |
{ | |
var modelSum = 0 | |
for (var index = 0; index < model.count; index++) | |
{ | |
modelSum += model.get(index).value | |
} | |
return modelSum | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment