Created
May 20, 2022 14:00
-
-
Save itarozzi/acddac38f0e681e4785486e83cff24c4 to your computer and use it in GitHub Desktop.
QtQuick and Canvas example
This file contains 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.Controls 1.4 | |
import "constant.js" as Constants | |
Item { | |
id: root | |
property int thevalue:35 | |
property bool editable: false | |
property int cTEMP_FASE_CALDA: 30 | |
width: 316 | |
height: 348 | |
onThevalueChanged: { | |
gaugeCanvas1.requestPaint() | |
gaugeCanvas2.requestPaint() | |
} | |
signal clicked | |
signal valueChanged | |
Rectangle { | |
id: ingombro | |
anchors.fill: parent | |
color: "black" | |
} | |
function formatValue(val) { | |
return Math.abs(val) | |
// if (val > 0) | |
// return "" + val | |
// else | |
// return "" + val | |
} | |
function value2rotation(val) { | |
// la rotazione va restituita come valore da moltiplicare a pi, tenendo conto che: | |
// min: 1*pi | |
// max: 2*pi | |
// mid: 1.5*pi | |
// Il reticolo fornito da Mario divide l'arco in 40 settori, quindi il valore deve necessariamente essere arrotondato | |
const NR_SETTORI = 40 | |
var ret | |
var val_max; | |
if (val === 0) ret = 1; | |
else { | |
if (val > 0) { | |
val_max = 44 | |
} | |
else { | |
val_max = 15 // valore assoluto | |
} | |
var angolo_settore = 1/NR_SETTORI | |
var settori_on = (NR_SETTORI * Math.abs(val) / val_max).toFixed(0) | |
ret = 1+(settori_on * angolo_settore) | |
//console.log("ROTATION RETVAL _:", val, angolo_settore, settori_on, ret) | |
} | |
//console.log("ROTATION RETVAL:", val, ret) | |
return ret | |
} | |
function angle2value(val) { | |
var ret | |
if (val <= 0) { | |
ret = (val/6) | |
} | |
else { | |
ret = (val/3) | |
} | |
if (ret > 45) ret = 45 | |
else if (ret < -15) ret = -15 | |
return ret | |
} | |
Behavior on width { | |
NumberAnimation {duration: 400} | |
} | |
// Behavior on height { | |
// NumberAnimation {duration: 400} | |
// } | |
Behavior on x{ | |
NumberAnimation {duration: 400} | |
} | |
Rectangle { | |
id: header | |
width: parent.width | |
height: parent.height * 0.075 | |
y:0 | |
color: "#649ccc" | |
Text { | |
id: tempLabel | |
text: qsTr("Temperatura") | |
font.capitalization: Font.AllUppercase | |
font.pixelSize: parent.height*0.7 | |
horizontalAlignment: Text.AlignHCenter | |
anchors.centerIn: parent | |
} | |
} | |
Rectangle { | |
width: parent.width | |
height: width | |
anchors.bottom: parent.bottom | |
color: "black" | |
border.color: Constants.COLOR_BLUE | |
border.width: 2 | |
Rectangle { | |
id: gaudeIndicator | |
width: parent.width - parent.border.width*2 | |
height: width*0.50 | |
x:parent.border.width | |
y:parent.height*0.15 | |
z:0 | |
color: Constants.COLOR_GREY | |
Canvas { | |
id: gaugeCanvas1 | |
anchors.fill: parent | |
z:5 | |
onPaint: { | |
var ctx = getContext("2d"); | |
ctx.reset(); | |
var centreX = width / 2; | |
var centreY = parent.height; | |
ctx.beginPath(); | |
if (thevalue < 0) | |
ctx.fillStyle = Constants.COLOR_WHITE | |
else ctx.fillStyle = Constants.COLOR_BLUE_LIGHT | |
ctx.moveTo(centreX, centreY); | |
ctx.arc(centreX, centreY, width / 2, 0, Math.PI*value2rotation(thevalue>cTEMP_FASE_CALDA?cTEMP_FASE_CALDA:thevalue), false); // Math.PI * 0.5, Math.PI * 2, false); | |
ctx.lineTo(centreX, centreY); | |
ctx.fill(); | |
} | |
} | |
Canvas { | |
id: gaugeCanvas2 | |
anchors.fill: parent | |
z:4 | |
visible: true | |
onPaint: { | |
var ctx = getContext("2d"); | |
ctx.reset(); | |
var centreX = width / 2; | |
var centreY = parent.height; | |
ctx.beginPath(); | |
ctx.fillStyle = Constants.COLOR_PURPLE_LIGHT | |
ctx.moveTo(centreX, centreY); | |
ctx.arc(centreX, centreY, width / 2, 0, Math.PI*value2rotation(thevalue), false); // Math.PI * 0.5, Math.PI * 2, false); | |
ctx.lineTo(centreX, centreY); | |
ctx.fill(); | |
} | |
} | |
} | |
Image { | |
id: gaugeBackground | |
source: "img/img_criolipo/maschera-led-tachimetro-base.png" | |
width: parent.width- (parent.border.width * 2) | |
height: parent.height * 0.60 | |
x:parent.border.width | |
y:parent.height* 0.15 | |
Image { | |
id: gauge88base | |
height: parent.height*0.37 | |
width: parent.width*0.54 | |
anchors.horizontalCenter: parent.horizontalCenter | |
y:parent.height * 0.39 | |
source: "img/img_criolipo/settaggio-tachimetro-88_base.png" | |
fillMode: Image.Stretch | |
z:5 | |
} | |
Image { | |
id: gauge_plus_minus | |
source: { | |
if (thevalue < 0) return "img/img_criolipo/meno-bianco.png" | |
else if (thevalue <= 30 ) return "img/img_criolipo/piu.png" | |
else return "img/img_criolipo/piu-viola.png" | |
} | |
visible: (thevalue != 0) | |
x:parent.width * 0.25 | |
y:parent.height * 0.48 | |
width: parent.width * 0.11 | |
height: width | |
fillMode: Image.PreserveAspectFit | |
z:5 | |
} | |
Image { | |
id: gauge_degree | |
source:{ if (thevalue < 0) return "img/img_criolipo/gradi-bianco.png" | |
else if (thevalue <= 30 ) return "img/img_criolipo/gradi.png" | |
else return "img/img_criolipo/gradi-viola.png" | |
} | |
x:parent.width * 0.695 | |
y:parent.height * 0.40 | |
width: parent.width * 0.06 | |
height: width | |
fillMode: Image.PreserveAspectFit | |
z:5 | |
} | |
Text { | |
id: value | |
x:parent.width * 0.37 | |
y:parent.height * 0.415 | |
width: parent.width*0.315 | |
z:10 | |
color: { | |
if (thevalue < 0) return Constants.COLOR_WHITE | |
else if (thevalue <= 30 ) return Constants.COLOR_BLUE_LIGHT | |
else return Constants.COLOR_PURPLE_LIGHT | |
} | |
font.pixelSize: parent.height *0.32 | |
font.family: "DSEG7Classic" | |
text: formatValue(thevalue) | |
horizontalAlignment: Text.AlignRight | |
} | |
Text { | |
id: tempUdm | |
text: qsTr("gradi centigradi") | |
font.capitalization: Font.AllUppercase | |
font.pixelSize: parent.height*0.07 | |
horizontalAlignment: Text.AlignHCenter | |
color: Constants.COLOR_BLUE | |
anchors.horizontalCenter: parent.horizontalCenter | |
y:parent.height*0.88 // il font a RT si posiziona piu in alto | |
} | |
} | |
MouseArea{ | |
anchors.fill: parent | |
onClicked: root.clicked() | |
onPositionChanged: { | |
if (editable) { | |
var delta_x = mouse.x - gaugeBackground.width/2 | |
var delta_y = mouse.y - gaugeBackground.height/2 | |
console.log(mouse.x + ", " + mouse.y + " => delta_x: " + delta_x + " - delta_y: " + delta_y) | |
var angle_radiant = Math.atan(delta_y/delta_x) | |
var angle = angle_radiant*180/Math.PI | |
if (delta_x > 0) angle+=180 | |
else if (delta_y > 0) angle+=360 | |
// Ruoto di 45 per avere lo zero allineato al gause | |
angle-=45 | |
if (angle>=180) angle = -360+angle | |
console.log("Angle -> " + angle_radiant + " >>> " + angle + "°") | |
root.thevalue = angle2value(angle) | |
} | |
} | |
onReleased: { | |
valueChanged(root.thevalue) | |
} | |
} | |
} | |
// Rectangle { | |
// color: "blue" | |
// width: 60 | |
// height: 60 | |
// MouseArea { | |
// anchors.fill: parent | |
// onClicked: thevalue-- | |
// } | |
// } | |
// Rectangle { | |
// color: "green" | |
// x:80 | |
// width: 60 | |
// height: 60 | |
// MouseArea { | |
// anchors.fill: parent | |
// onClicked: thevalue++ | |
// } | |
// } | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment