Skip to content

Instantly share code, notes, and snippets.

@peteristhegreat
Last active July 29, 2016 03:38
Show Gist options
  • Save peteristhegreat/00bbbdd045b51815935dd80ffe48f902 to your computer and use it in GitHub Desktop.
Save peteristhegreat/00bbbdd045b51815935dd80ffe48f902 to your computer and use it in GitHub Desktop.
qt-quick-qml-and-canvas-tutorial pie chart example
// 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
}
}
}
// 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();
}
}
//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