Ancrages (Anchors)
left: Bord gaucheright: Bord droittop: Bord supérieurbottom: Bord inférieurcenterIn: Centré dans le parentfill: Remplir complètement le parentverticalCenter: Centré verticalementhorizontalCenter: Centré horizontalement
Exemple d'ancrage :
parent.anchors.left: parent // Positionne l'élément sur le bord gauche de son parent
Rotation
La propriété rotation permet de faire pivoter un élément instantanément.
Exemple de rotation lors d'un clic :
onClicked: wheel.rotation += 90 // L'objet 'wheel' tourne de 90 degrés lors d'un clic
Animations pour la Rotation
Pour rendre la rotation fluide, on utilise des comportements animés.
Image {
id: rootElement
Image {
id: wheel
// Définit le comportement lors de la modification de la propriété 'rotation'
Behavior on rotation {
NumberAnimation { // Utilise une animation numérique
duration: 250 // Durée de l'animation : 250 millisecondes
}
}
}
}
Modules Fondamentaux de Qt
Présentation des Modules
Qt est organisé en plusieurs modules qui fournissent des fonctionnalités spécifiques.
| Module | Description |
|---|---|
| Qt Core | Classes de base non graphiques, essentielles pour les autres modules. |
| Qt GUI | Classes de base pour les interfaces graphiques (GUI), incluant OpenGL. |
| Qt Multimedia | Fonctionnalités pour l'audio, la vidéo, la radio et la caméra. |
| Qt Network | Classes simplifiant la programmation réseau. |
| Qt QML | Support pour les classes QML et le langage JavaScript. |
| Qt Quick | Framework pour la création d'interfaces utilisateur dynamiques et personnalisées. |
| Qt SQL | Classes pour l'intégration avec les bases de données SQL. |
| Qt Test | Classes pour les tests unitaires des applications et bibliothèques Qt. |
| Qt WebKit | Implémentation de base de WebKit2 avec une nouvelle API QML. |
| Qt WebKit Widgets | Classes de base pour les widgets intégrant WebKit1 de Qt4. |
| Qt Widgets | Classes de widgets C++ étendant le module Qt GUI. |
Structure des dépendances principales :
Création d'un Projet Qt
Nouveau Projet Qt Quick
Qt Creator propose plusieurs modèles pour démarrer un projet Qt Quick :
- Swipe : Cadre pour la navigation entre plusieurs pages par balayage, avec des boutons de tabulation.
- Scroll : Cadre pour des listes déroulantes avec une barre de défilement.
- Stack : Cadre basé sur une pile, avec une page principale et des sous-pages.
- Empty : Projet vide, ne contenant qu'une fenêtre "Hello World".
Premier Programme "Hello World"
Créons un projet vide nommé QML_helloworld.
La structure typique d'un tel projet est la suivante :
QML_helloworld
└─QML_helloworld.pro // Fichier de projet Qt
└─Sources
└─main.cpp // Fichier C++ principal
└─Resources
└─qml.qrc // Fichier de ressources Qt
└─/
└─main.qml // Fichier QML principal
Le fichier main.cpp charge et exécute le fichier QML. Pour lier les données C++ à l'interface QML, il faut explorer la syntaxe QML.
Voici un exemple simple de QML créant un rectangle avec le texte "Hello, World" et une fonctionnalité de sortie :
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
width: 360
height: 360
color: '#EE00EE' // Couleur violette
Text {
id: helloText
anchors.centerIn: parent
text: qsTr("Hello, World")
}
MouseArea {
anchors.fill: parent // La zone de clic couvre tout le rectangle
onClicked: {
Qt.quit(); // Quitte l'application
}
}
}
}
Avantages de Qt Quick
Qt Quick permet une séparation claire entre le développement front-end (interface utilisateur) et back-end (logique métier). L'interface est définie en QML, un langage déclaratif similaire à HTML, tandis que la logique peut être implémentée en C++. Cela facilite les mises à jour d'interface sans impacter la logique principale.
Débogage (Debugging)
Le débogage QML se fait dans Qt Creator, de manière similaire au débogage C++.
Raccourcis utiles dans Qt Creator :
Ctrl+B: Construire le projetCtrl+R: Exécuter le projetCtrl+Tab: Changer de document ouvertCtrl+k: Ouvrir le localisateurEsc: Revenir en arrièreF2: Afficher la définition d'un symboleF4: Basculer entre fichier d'en-tête et fichier source (pour C++)
Introduction à la Syntaxe QML
Syntaxe Générale
import: Importe un module QML et sa version (ex:import QtQuick 2.9).- Commentaires : Similaires à C++ et JavaScript (
//ou/* */). - Éléments : Chaque fichier QML doit avoir un élément racine. Les éléments sont définis par des accolades
{}. Les propriétés sont sous la formenom: valeur. Les éléments peuvent être imbriqués et référencés par leurid. Le mot-cléparentpermet d'accéder à l'élément parenet. - Aperçu (Preview) : Utilisez
qmlscenepour visualiser un fichier QML :$QTDIR/bin/qmlscene mon_fichier.qml.
Caractéristiques des Propriétés
id: Identifiant unique d'un élément dans le scope actuel, similaire à un pointeur en C++.- Valeurs par défaut : Les propriétés non initialisées prennent une valeur par défaut définie dans la documentation de l'élément.
- Liaisons de Propriétés (Property Binding) : Une propriété peut dépendre d'autres propriétés. Sa valeur est mise à jour automatiquemant lorsque les propriétés dont elle dépend changent.
- Propriétés personnalisées : Définies avec le mot-clé
property(ex:property int score: 0). Si une propriété est destinée à être la propriété principale, on peut utiliserdefault. - Alias de Propriétés :
property alias nom: autreElement.proprietepermet d'exposer une propriété d'un sous-élément à l'extérieur du composant. - Propriétés groupées : Les propriétés d'un même groupe peuvent être définies de manière compacte (ex:
font { family: "Ubuntu"; pixelSize: 24 }).
Signaux
Les signaux sont déclenchés lorsque des événements se produisent, comme le changement d'une propriété.
on<Propriete>Changed: Signal émis quand une propriété change (ex:onHeightChanged: console.log('height:', height)).Keys.onSpacePressed: Signal déclenché lors de l'appui sur la barre d'espace.Keys.onEscapePressed: Signal déclenché lors de l'appui sur la touche Échap.
Portée des Identifiants (ID Scope)
Les id sont uniques au sein d'un fichier QML. Pour exposer des éléments à l'extérieur, on utilise des alias ou des propriétés exportées sur l'élément racine. Il faut être prudent avec les mécanismes qui peuvent écraser des IDs lors du chargement dynamique de composants.
Scripts JavaScript
QML peut intégrer du JavaScript pour des logiques plus complexes.
Text {
id: label
x: 24; y: 24
width: 360
height: 360
color: '#aaaaaa'
property int spacePresses: 0
text: "Space pressed: " + spacePresses + " times" // Liaison de propriété
onTextChanged: console.log("text changed to: ", text)
focus: true // Nécessaire pour recevoir les événements clavier
Keys.onSpacePressed: {
increment() // Appel de la fonction JavaScript
}
Keys.onEscapePressed: {
label.text = '' // Affectation simple, rompt la liaison de propriété précédente
}
function increment() {
spacePresses = spacePresses + 1 // Affectation simple
}
}
Notez la différence entre l'affectation simple (= dans une fonction JavaScript) qui n'est exécutée qu'une fois, et la liaison de propriété qui est active pendant toute la durée de vie de l'élément.
Éléments de Base
Types d'Éléments
- Visuels : Ont une représentation graphique (ex:
Rectangle,Text,Image). - Non-visuels : Fournissent des fonctionnalités (ex:
Timer).
Éléments Visuels Courants
Item: L'élément de base de tous les éléments visuels. Il ne dessine rien mais définit les propriétés communes (position, taille, ancrages, transformations, visibilité, états). Il sert souvent de conteneur.Rectangle: ÉtendItemen ajoutant la possibilité de remplir avec une couleur et de définir des bordures et des coins arrondis.Text: Affiche du texte. Les propriétés commefont,color,horizontalAlignment,verticalAlignmentcontrôlent son apparence.Image: Affiche des images. La propriétésourcespécifie le fichier image, etfillModecontrôle comment l'image est adaptée.MouseArea: Permet de capturer les événements de souris pour un élément, sans être visible elle-même.
Item (l'Élément de Base)
Propriétés communes des éléments visuels :
- Géométrie :
x,y,width,height,z(ordre d'empilement). - Mise en page :
anchors(positionnement par rapport au parent ou à d'autres éléments),margins. - Gestion clavier :
focus,Keys. - Transformations :
scale,rotation,transformOrigin. - Visuel :
opacity,visible,clip,smooth. - États :
states,transitionspour gérer les changements d'état animés.
Rectangle (Élément Rectangulaire)
Permet de créer des formes rectangulaires colorées avec des bordures et des coins arrondis.
Rectangle {
id: rect1
x: 10; y: 10
width: 75; height: 95
color: "lightsteelblue" // Couleur unie
}
Rectangle {
id: rect2
x: 110; y: 12
width: 75; height: 95
color: "white"
border.color: "lightsteelblue"
border.width: 5
radius: 8 // Coins arrondis
}
Les couleurs peuvent être spécifiées par nom, hexadécimal (#RRGGBB) ou RGB. Les dégradés sont possibles avec la propriété gradient.
Rectangle {
id: rectGradient
width: 175; height: 95
gradient: Gradient { // Définition du dégradé
GradientStop { position: 0.0; color: "lightsteelblue" }
GradientStop { position: 0.5; color: "slategray" }
GradientStop { position: 1.0; color: "lightsteelblue" }
}
border.color: "slategray"
}
Il faut définir width et height pour qu'un rectangle soit visible.
Text (Élément Texte)
Affiche du texte. Les propriétés clés sont text, font (family, pixelSize), color.
Text {
text: "Bonjour le Monde !"
font.family: "STXinwei" // Police spécifique (doit être installée sur le système)
color: "#333333"
font.pixelSize: 28
}
Il est possible de charger des polices personnalisées avec FontLoader.
Alignement : horizontalAlignment (AlignLeft, AlignHCenter, AlignRight, AlignJustify) et verticalAlignment (AlignTop, AlignVCenter, AlignBottom).
Text {
x: 50; y: 50
width: 150; height: 120 // Largeur et hauteur définies pour le retour à la ligne
text: 'Un texte très long qui doit passer à la ligne'
wrapMode: Text.WordWrap // Retour à la ligne aux mots
style: Text.Sunken // Effet de texte enfoncé
styleColor: '#FF4444'
verticalAlignment: Text.AlignTop
font.pixelSize: 20
}
Gestion du texte long :
elide: Ajoute des points de suspension (ElideMiddle,ElideLeft,ElideRight,ElideNone).wrapMode: Gère le retour à la ligne (WordWrap,WrapAnywhere,NoWrap). Nécessite la définition d'une largeur.
Le Text n'a pas de fond par défaut ; il faut utiliser un Rectangle comme conteneur pour ajouter un fond.
Image (Élément Image)
Affiche des images (PNG, JPG, GIF, etc.).
Image {
x: 12; y: 12
source: "image/rocket.png" // Chemin vers l'image
}
Image {
x: 112; y:12
width: 48
height: 118/2
source: "image/rocket.png"
fillMode: Image.PreserveAspectCrop // Adaptation avec rognage
clip: true // Assure que l'image est rognée aux limites de l'élément
}
Propriété fillMode (modes d'adaptation) :
Stretch: Étire l'image pour remplir.PreserveAspectFit: Redimensionne uniformément pour tenir sans rogner.PreserveAspectCrop: Redimensionne uniformément pour remplir, en rognant si nécessaire.Tile: Répète l'image horizontalement et verticalement.Pad: Affiche l'image sans transformation.
La propriété clip (activée à true) contraint le dessin de l'élément à ses limites.
MouseArea (Zone Souris)
Un élément non visuel pour capturer les événements de souris (clic, survol, etc.) sur une zone définie.
Rectangle {
id: rectContainer
width: 100; height: 100
color: "lightblue"
MouseArea {
anchors.fill: parent // La zone souris couvre tout le rectangle parent
onClicked: console.log("Rectangle clicked!") // Action lors du clic
}
}
Composants (Components)
Un composant est un élément réutilisable. On peut les créer en créant un fichier QML séparé (ex: Button.qml).
// Button.qml
import QtQuick 2.0
Item { // L'élément racine est un Item, bon pour l'encapsulation
id: rootComponent
property alias buttonText: label.text // Expose la propriété 'text' du Text interne
signal clicked // Définit un signal personnalisé
Rectangle {
id: buttonRect
width: 110; height: 25
color: "lightsteelblue"
border.color: "slategrey"
Text {
id: label
anchors.centerIn: parent
text: "Start" // Valeur par défaut
}
MouseArea {
anchors.fill: parent
onClicked: {
statusText.text = "Button clicked!" // Change un texte interne
rootComponent.clicked() // Émet le signal personnalisé
}
}
}
Text { // Un élément interne pour montrer le statut
id: statusText
x: 10; y: 75
width: 110; height: 25
text: "Waiting..."
horizontalAlignment: Text.AlignHCenter
}
}
Utilisation du composant Button.qml :
// Fichier principal (ex: main.qml)
import QtQuick 2.9
Window {
// ... autres propriétés ...
Button { // Utilisation du composant personnalisé
id: myButton
x: 12; y: 12
buttonText: "Click Me!" // Définit la propriété exposée 'buttonText'
onClicked: { // Réagit au signal 'clicked' du composant
statusDisplay.text = "Clicked!"
}
}
Text {
id: statusDisplay
x: 12; y: 75
width: 110; height: 25
text: "Waiting..."
horizontalAlignment: Text.AlignHCenter
}
}
Transformations Simples
Les transformations (translation, rotation, échelle) modifient l'apparence des éléments.
Un composant d'image cliquable pour démonstration :
// ClickableImage.qml
import QtQuick 2.0
Image {
id: root
signal clicked // Signal pour notifier les clics
MouseArea {
anchors.fill: parent
onClicked: root.clicked() // Émet le signal quand on clique sur l'image
}
}
Utilisation du composant et application de transformations :
Image { id: bg; source: "image/blue.png" } // Fond d'écran
MouseArea { // Permet de réinitialiser les transformations en cliquant sur le fond
anchors.fill: parent
onClicked: {
rocket1.x = 20
rocket2.rotation = 0
rocket3.rotation = 0
rocket3.scale = 1.0
}
}
ClickableImage {
id: rocket1
x: 20; y: 100
source: "image/rocket.png"
onClicked: {
x += 5 // Déplace l'image vers la droite
}
}
ClickableImage {
id: rocket2
x: 140; y: 100
source: "image/rocket.png"
smooth: true // Améliore la qualité du rendu
onClicked: {
rotation += 5 // Ajoute 5 degrés à la rotation
}
}
ClickableImage {
id: rocket3
x: 240; y: 100
source: "image/rocket.png"
smooth: true
onClicked: {
rotation += 5 // Ajoute 5 degrés à la rotation
scale -= 0.05 // Réduit l'échelle de 0.05
}
}
Ordre d'empilement (Z-order) : Les éléments sont dessinés dans l'ordre où ils apparaissent dans le code. Les éléments ultérieurs sont au-dessus des précédents. La propriété z peut être utilisée pour contrôler explicitement cet ordre.
Éléments de Positionnement
Qt Quick fournit des conteneurs pour organiser automatiquement les éléments enfants : Row, Column, Grid, Flow.
Créons quelques composants de base pour l'exemple :
// RedSquare.qml
import QtQuick 2.0
Rectangle {
width: 48; height: 48; color: "#ee0000"
border.color: Qt.lighter(color)
}
Column (Disposition Colonne)
Organise les enfants verticalement avec un espacement.
Rectangle { // Conteneur principal
width: 150; height: 300
anchors.centerIn: parent
Column {
anchors.centerIn: parent
spacing: 10 // Espacement entre les lignes
RedSquare {}
GreenSquare { width: 100 } // Les tailles peuvent être spécifiées
BlueSquare {}
}
}
Row (Disposition Ligne)
Organise les enfants horizontalement avec un espacement.
Rectangle { // Conteneur principal
width: 300; height: 240
anchors.centerIn: parent
Row {
anchors.centerIn: parent
spacing: 15 // Espacement entre les colonnes
RedSquare {}
GreenSquare {}
BlueSquare {}
LighterSquare {}
}
}
Grid (Disposition Grille)
Organise les enfants en grille avec un nombre défini de lignes et de colonnes.
Rectangle { // Conteneur principal
width: 300; height: 240
anchors.centerIn: parent
Grid {
rows: 2
columns: 2
anchors.centerIn: parent
spacing: 15
RedSquare {}
GreenSquare {}
BlueSquare {}
LighterSquare {}
}
}
Flow (Disposition Flux)
Similaire à Grid mais s'adapte intelligemment à la largeur et la hauteur des éléments.
Rectangle { // Conteneur principal
width: 300; height: 240
anchors.centerIn: parent
Flow {
anchors.fill: parent
anchors.margins: 20
spacing: 15
RedSquare { width: 20 }
GreenSquare { height: 60 }
BlueSquare { width: 75 }
LighterSquare { height: 90 }
}
}
Repeater (Répéteur)
Utilisé pour créer plusieurs instances d'un élément, souvent en combinaison avec des dispositions.
Points Clés
- La concaténation d'un entier et d'une chaîne de caractères avec
+convertit automatiquement l'entier en chaîne. - Pour rendre un élément réactif aux événements clavier, il faut définir
focus: true. La couleur peut changer en fonction de l'état de focus :color: focus ? "red" : "black".