Accès rapide :
Rappel sur les liens entre QtQuick/QML et Chromium
Obtenir un contexte de tracé
Tracé un polygone fermé
Quelques autres primitives de tracé
Pour rappel, le moteur QtQuick embarque le moteur Web Chromium (le projet au coeur du navigateur Chrome de la société Google). Chromium est un projet « Open Source » qui est développé par « The Chromium Project ». Vous pouvez consulter le site http://www.chromium.org/Home pour de plus amples informations.
Ce que cela implique pour nous développeurs QtQuick/QML, c'est que bon nombre d'APIs Web sont aussi accessibles en QML. Et notament les APIs « Canvas », les « WebWorkers » (appelés « WorkerScripts » en QtQuick/QML), XmlHttpRequest, ...
Donc si vous maitrisez déjà un peu le développement Web et l'utilisation des Canvas dans ce contexte, alors je n'ai presque plus rien à vous expliquer et vous saurez déjà produire plein de type de tracés en Qt. Si ce n'ai pas le cas, rien de grave : nous allons maintenant un peu présenter cette API.
La première des choses à faire pour dessiner dans un « canvas » est de produire le composant graphique dans votre fichier QML.
La classe Canvas
est présente dans le paquetage QtQuick
: aucun autre import n'est requis pour son utilisation.
Voici comment instancier un composant Canvas
.
import QtQuick Window { id: "window" width: 600 height: 300 visible: true title: qsTr("QtQuick Canvas demonstration") Canvas { id: canvas anchors.fill: parent } }
Bien entendu, si vous lancez l'application telle quelle, aucun tracé ne sera produit.
Pour passer à l'étape suivante, il vous faudra acquérir un contexte de tracé : c'est l'objet le plus important de l'API Canvas.
Ce contexte de tracé devra être utilisé à chaque fois que le canvas devra se redessiner : pour ce faire nous allons abonner un signal handler sur
l'événement onPaint
du canvas. Voici un exemple de code.
import QtQuick Window { id: "window" width: 600 height: 300 visible: true title: qsTr("QtQuick Canvas demonstration") Canvas { id: canvas anchors.fill: parent onPaint: function() { // On acquière le contexte de tracé. let context = canvas.getContext("2d"); } } }
Votre contexte de tracé peut être configuré sur de nombreuses caractéristiques : couleur du stylo, type de tracé (plein, hachuré...), la couleur de remplissage (en cas de formes complexes), la couleur de détourage... Voici un exemple de configuration du contexte de tracé.
import QtQuick Window { id: "window" width: 600 height: 300 visible: true title: qsTr("QtQuick Canvas demonstration") Canvas { id: canvas anchors.fill: parent onPaint: function() { // On acquière le contexte de tracé. let context = canvas.getContext("2d"); // On fixe l'épaisseur de tracé du contexte de tracé. context.lineWidth = 4 // On fixe la couleur de détourage en noir. context.strokeStyle = "black" // On fixe la couleur de remplissage en rouge. context.fillStyle = "red" // ... Suite du code ... } } }
Commençons par faire un premier tracé simple : nous allons dessiner un polygone fermé. Bien que plusieurs types de code permettraient d'arriver au même
résultat, nous allons utiliser la notion de path (de chemin). Un path consiste en un ensemble de points définissant le polygone (dans l'exemple, un simple
carré). Le path pourra être fermé ou non, mais dans notre cas nous souhaitons parler d'un polygone ce qui implique que le chemin sera fermé.
Pour initier un chemin, il faut invoquer la méthode beginPath
sur le contexte. Pour fermer le chemin (revenir au point de départ), il faut
invoquer la méthode endPath
. Voici un exemple d'utilisation.
import QtQuick Window { id: "window" width: 600 height: 300 visible: true title: qsTr("QtQuick Canvas demonstration") Canvas { id: canvas anchors.fill: parent onPaint: function() { // On acquière le contexte de tracé. let context = canvas.getContext("2d"); // On configure le contexte de tracé. context.lineWidth = 4 context.strokeStyle = "black" context.fillStyle = "red" // On définit un chemin correspondant à un carré. context.beginPath() context.moveTo(50, 50) context.lineTo(150, 50) context.lineTo(150, 150) context.lineTo(50, 150) context.closePath() // On détoure (stroke) et on remplit (fill) le chemin. context.fill() context.stroke() } } }
Voici le résultat produit par cet exemple de code.
Vous pouvez aussi configurer votre contexte de tracé pour utiliser des dégradés de couleur. L'exemple suivant change la couleur de remplissage du carré par un dégradé.
import QtQuick Window { id: "window" width: 600 height: 300 visible: true title: qsTr("QtQuick Canvas demonstration") Canvas { id: canvas anchors.fill: parent onPaint: function() { // On acquière le contexte de tracé. let context = canvas.getContext("2d"); // On configure le contexte de tracé. context.lineWidth = 4 context.strokeStyle = "black" let fillGradient = context.createLinearGradient(100, 50, 100, 150); fillGradient.addColorStop(0, "red"); fillGradient.addColorStop(0.33, "yellow"); fillGradient.addColorStop(1.0, "green"); context.fillStyle = fillGradient // context.fillStyle = "red" // On définit un chemin correspondant à un carré. context.beginPath() context.moveTo(50, 50) context.lineTo(150, 50) context.lineTo(150, 150) context.lineTo(50, 150) context.closePath() // On détoure (stroke) et on remplit (fill) le chemin. context.fill() context.stroke() } } }
createLinearGradient
correspondent au sens du dégradé.
Ici du haut (100, 50) vers le bas (100, 150). Mais rien ne vous empêche de réaliser un dégradé de couleurs en diagonal.
Et voici le résultat produit par cet exemple de code.
Il existe de très nombreuses primitives de tracé proposées par un canvas. En voici quelques-unes.
arc : permet de tracer un arc de cercle.
fillText : permet de tracer un texte à l'écran.
lineTo : permet de tracer une ligne de la position courante à la position spécifiée en paramètre.
moveTo : permet de déplacer le contexte de tracé à la position spécifiée en paramètre.
quadraticCurveTo : permet de tracer une courbe quadratique.
Voici un exemple un peu plus riche que l'exemple précédent. On y trace le smiley suivant : oui, je l'ai fait un peu loucher ;-)
Et voici le code QML correspondant.
import QtQuick Window { id: "window" width: 200 height: 200 visible: true title: qsTr("QtQuick Canvas demonstration") Canvas { id: canvas anchors.fill: parent antialiasing: true onPaint: function() { let ctx = canvas.getContext("2d"); // On trace la face rose de notre smiley. context.strokeStyle = "#000000"; context.fillStyle = "#FF00FF"; context.beginPath(); context.arc(100, 100, 50, 0, Math.PI*2, true); context.closePath(); context.stroke(); context.fill(); // On dessine l'oeil gauche positionné en 80, 80. context.strokeStyle = "#000000"; context.fillStyle = "#FFFFFF"; context.beginPath(); context.arc(80, 80, 8, 0, Math.PI*2, true); context.closePath(); context.stroke(); context.fill(); context.fillStyle = "#009966"; context.beginPath(); context.arc(83, 80, 5, 0, Math.PI*2, true); context.closePath(); context.fill(); // On dessine l'oeil droit positionné en 120, 80. context.strokeStyle = "#000000"; context.fillStyle = "#FFFFFF"; context.beginPath(); context.arc(120, 80, 8, 0, Math.PI*2, true); context.closePath(); context.stroke(); context.fill(); context.fillStyle = "#009966"; context.beginPath(); context.arc(117, 80, 5, 0, Math.PI*2, true); context.closePath(); context.fill(); // On trace le nez, via un path. context.fillStyle = "#000000"; context.beginPath(); context.moveTo(93, 100); context.lineTo(100, 93); context.lineTo(107, 100); context.lineTo(100, 107); context.closePath(); context.fill(); // On trace la bouche via deux courbes quadratiques. context.strokeStyle = "#000000"; context.beginPath(); context.moveTo(70, 110); context.quadraticCurveTo(100, 150, 130, 110); context.quadraticCurveTo(100, 150, 70, 110); context.closePath(); context.stroke(); } } }
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :