Skip to content

Instantly share code, notes, and snippets.

@itarozzi
Created May 20, 2022 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itarozzi/acddac38f0e681e4785486e83cff24c4 to your computer and use it in GitHub Desktop.
Save itarozzi/acddac38f0e681e4785486e83cff24c4 to your computer and use it in GitHub Desktop.
QtQuick and Canvas example
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