CheckZone
CheckXXXX sont des classes de cases à cocher, genre "j'ai lu les conditions de vente". Comme bouton, c'est comme un bouton de lumière avec télérupteur. Lorsque l'on appuie dessus il change d'état. Pour cette bibliothèque, lorsqu'on appuie dessus, si il n'est pas actif, il le devient, et un événement onSelect est généré. Si il était déjà actif, il se désactive et un événement onUnselect est généré. Lorsque l'on relâche l'appui, ou si l'appui sort de la zone d'action, il ne se passe rien.
XXXXZone sont des classes de boutons sans dessin prédéfini. En principe, on affiche une image de fond qui va servir de zone visible pour les boutons de cette classe.
CheckZone est donc une classe de cases à cocher sans dessin prédéfini.
Exemples d'utilisation
CheckZone bouton(0,0,LARGEUR,HAUTEUR); // Crée bouton sur toute la surface de l'écran CheckZone bouton(150,100,170,120); // Crée bouton au centre en mode PAYSAGE 320x240 CheckZone bouton = new CheckZone(100,100,120,120); // Crée une instance dynamique bouton new CheckZone(100,100,120,120); // Crée une instance dynamique bouton sans pointeur dessus circle(bouton.demiX1+bouton.demiX2, bouton.demiY1+bouton.demiY2, 10); // Cercle centré sur le bouton bouton.onSelectFunction = &action; // Appel la fonction void action(void) lors de lors de la sélection bouton.onUnselectFunction = &action; // Appel la fonction void action(void) lors de la désélection if (bouton.isSelect())... // Si la case est cochée ...
Référence
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
class CheckZone public: CheckZone(int x1, int y1, int x2, int y2); byte demiX1, demiY1, demiX2, demiY2; word buttonColor; void (*onSelectFunction)(void); void (*onUnselectFunction)(void); CheckZone *controleSuivant; void select(void); void unselect(void); boolean isSelected(void); virtual void onSelect(void); virtual void onUnselect(void) virtual void drawButton(void);
Attributs et méthodes
CheckZone(): Constructeur, s'insère dans la liste des contrôles gérées. x1, y1, x2, y2: zone d'action
demiX1, demiY1, demiX2, demiY2: Occupation de l'espace dans l'écran, coordonnés absolues DIVISEES par 2
buttonColor: Couleur du fond des boutons de la classe
*onSelectFunction: : Pointeur sur la fonction à appeler lorsque le bouton est sélectionné
*onUnselectFunction: : Pointeur sur la fonction à appeler lorsque le bouton est désélectionné
*controleSuivant: Pointeur sur le contrôle suivant dans la liste des contrôles
select(): : Active un bouton.
unselect(): : Désactive ce bouton
isSelected(): : Informe de l'état du bouton.
onSelect(): : Fonction appelée lors de la sélection. On peut surcharger cette fonction, par défaut elle est vide
onUnselect(): : Fonction appelée lors de la désélection. On peut surcharger cette fonction, par défaut elle est vide
drawButton(): : Fonction appelée lors de l'activation, la désactivation, à l'initialisation de la librairie ou sur appel de la
fonction drawControles(). On peut surcharger cette fonction, par défaut elle est vide pour les boutons XXXXZone, et fait ce qu'il faut pour les autres. On
peut surcharger cette méthode, mais si on veut garder le dessin par défaut, il faut appeler la méthode drawButton() de la classe mère.
Voir aussi
- scanEvent(); Moteur de la gestion des événements
- PushZone; Bouton poussoir sans dessin
- CheckCoche; Bouton bistable (va vient) case à cocher
- CheckCircle; Bouton bistable (va vient) rond
- RadioZone; Bouton radio (un seul bouton actif parmi plusieurs) sans dessin
Notes
Pour définir un bouton, il faut donner sa zone d'action. Pour des raisons de stockage mémoire et de précision, n'est enregistré que les nombres pairs des valeurs passées. Les nombres impairs sont arrondis au nombre pair inférieur. Ainsi la zone (100,100,201,201) est équivalente à (100,100,200,200).
Si on a plusieurs boutons dont les zones d'actions ont une partie commune, comme les boutons sont analysés dans l'ordre inverse de leur déclaration, la zone commune devient propriété du bouton défini en dernier. Cela évite les conflits. Cela permet aussi d'avoir un bouton dont la zone n'est pas rectangulaire, il peut manquer un coin.
Exemples
Dans les exemples qui suivent trois boutons sont placées à droite de l'écran. Leur définition est statique, on peut aussi les passer en dynamique, cela ne change rien. Il y a plusieurs implantations possibles pour lire l'état des boutons et l'afficher. J'en montre ici 5, il y en a d'autres, par exemple par la lecture de la liste des contrôles. Le programme affiche l'état des boutons.
Premier exemple: 3 fonctions externes
PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-920-CheckZone-3-onSelectFunction\Exemple-920-CheckZone-3-onSelectFunction.ino (dans votre fichier téléchargé):
// Mise en place de 3 boutons de type CheckZone (zone à cocher, pas de dessin // dans le bouton). Quand on appuie sur un bouton, un disque blanc montre son // activité // Version 1: // - Les boutons ont une définition statique // - Utilise onSelectFunction pour exécuter l'action à faire // - Une action différente pour chaque bouton # $menu = ":PG"; include <PecheuxGraph_ILI9341_8bits.h> // Appel de la bibliothèque // Déclaration statique des instances, doit se faire en dehors du setup // Dans ce cas les boutons sont accessibles partout CheckZone boutonHaut(190, 90, 230, 130); // Bouton en haut CheckZone boutonCentre(190, 140, 230, 180); // Bouton au centre CheckZone boutonBas(190, 190, 230, 230); // Bouton en bas // Déclaration de 3 fonctions, une par bouton, qui feront ce qu'il faut // faire à chaque changement // Ces fonctions ne doivent pas avoir de paramètres et ne doit rien retourner // Les noms peuvent être quelconques void onSelectActionHaut() // Action à faire quand on appuie sur le bouton du haut { if (boutonHaut.isSelected()) fillCircle(30, 110, 20, WHITE); else fillCircle(30, 110, 20, BLACK); } void onSelectActionCentre() // Action à faire quand on appuie sur le bouton du centre { if (boutonCentre.isSelected()) fillCircle(30, 160, 20, WHITE); else fillCircle(30, 160, 20, BLACK); } void onSelectActionBas() // Action à faire quand on appuie sur le bouton du bas { if (boutonBas.isSelected()) fillCircle(30, 210, 20, WHITE); else fillCircle(30, 210, 20, BLACK); } void setup() { setGraphMode(PAYSAGE); // Initialisation de la carte rect(190, 90, 230, 130,GREEN); // Carré du haut rect(190, 140, 230, 180); // Carré au centre de l'écran rect(190, 190, 230, 230); // Carré du bas text(F("Appuyez sur un carré")); boutonHaut.onSelectFunction=&onSelectActionHaut; // Fonction appelée si on active le bouton du haut de l'écran boutonCentre.onSelectFunction=&onSelectActionCentre; // Fonction appelée si on active le bouton au milieu de l'écran boutonBas.onSelectFunction=&onSelectActionBas; // Fonction appelée si on active le bouton en bas de l'écran boutonHaut.onUnselectFunction=&onSelectActionHaut; // Fonction appelée si on désactive le bouton du haut de l'écran boutonCentre.onUnselectFunction=&onSelectActionCentre; // Fonction appelée si on désactive le bouton au milieu de l'écran boutonBas.onUnselectFunction=&onSelectActionBas; // Fonction appelée si on désactive le bouton en bas de l'écran } void loop() { scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans le loop }
Résultat:

Deuxième exemple: 1 fonction externe indifférenciée
PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-921-CheckZone-1-onSelectFunction\Exemple-921-CheckZone-1-onSelectFunction.ino (dans votre fichier téléchargé):
// Mise en place de 3 boutons de type CheckZone (zone à cocher, pas de dessin // dans le bouton). Quand on appuie sur un bouton, un disque blanc montre son // activité // Version 2: // - Les boutons ont une définition statique // - Utilise onSelectFunction pour exécuter l'action à faire // - Une seule action pour les trois boutons, qui ne fait pas de différence entre les boutons # $menu = ":PG"; include <PecheuxGraph_ILI9341_8bits.h> // Appel de la bibliothèque // Déclaration statique des instances, doit se faire en dehors du setup // Dans ce cas les boutons sont accessibles partout CheckZone boutonHaut(190, 90, 230, 130); // Bouton en haut CheckZone boutonCentre(190, 140, 230, 180); // Bouton au centre CheckZone boutonBas(190, 190, 230, 230); // Bouton en bas // Déclaration d'une fonction qui fera ce qu'il faut faire à chaque changement // Cette fonction ne doit pas avoir de paramètres et ne doit rien retourner // Le nom peut être quelconque void onSelectAction() // Action à faire quand on appuie sur un bouton { if (boutonHaut.isSelected()) fillCircle(30, 110, 20, WHITE); // On s'occupe du premier bouton else fillCircle(30, 110, 20, BLACK); if (boutonCentre.isSelected()) fillCircle(30, 160, 20, WHITE); // Puis du deuxième else fillCircle(30, 160, 20, BLACK); if (boutonBas.isSelected()) fillCircle(30, 210, 20, WHITE); // Puis du troisième else fillCircle(30, 210, 20, BLACK); } void setup() { setGraphMode(PAYSAGE); // Initialisation de la carte rect(190, 90, 230, 130,GREEN); // Carré du haut rect(190, 140, 230, 180); // Carré au centre de l'écran rect(190, 190, 230, 230); // Carré du bas text(F("Appuyez sur un carré")); // Ici j'utilise pour l'exemple la triple affectation. Au lieu d'écrire a=1; b=1; c=1; on peut // écrire a=b=c=1 Cela doit se lire j'affecte 1 à c, cette affectation prned la valeur 1 et c'est // cette valeur que j'affecte à b. Cette nouvelle affectation retourne 1 que j'affecte à a. boutonHaut.onSelectFunction= // Fonction appelée si on active le bouton du haut de l'écran boutonCentre.onSelectFunction= // Fonction appelée si on active le bouton au milieu de l'écran boutonBas.onSelectFunction=&onSelectAction; // Fonction appelée si on active le bouton en bas de l'écran boutonHaut.onUnselectFunction= // Fonction appelée si on désactive le bouton du haut de l'écran boutonCentre.onUnselectFunction= // Fonction appelée si on désactive le bouton au milieu de l'écran boutonBas.onUnselectFunction=&onSelectAction; // Fonction appelée si on désactive le bouton en bas de l'écran } void loop() { scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans le loop }
Résultat:
Le fonctionnement est exactement le même que pour le premier exemple. C'est juste une histoire d'implantation.
Troisième exemple: 1 fonction tri sur l'ordonnée
PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-922-CheckZone-Suivant-ordonnee\Exemple-922-CheckZone-Suivant-ordonnee.ino (dans votre fichier téléchargé):
// Mise en place de 3 boutons de type CheckZone (zone à cocher, pas de dessin // dans le bouton). Quand on appuie sur un bouton, un disque blanc montre son // activité // Version 3: // - Les boutons ont une définition statique // - Utilise onSelectFunction pour exécuter l'action à faire // - Une seule action pour les trois boutons, différence faites sur les coordonnées # $menu = ":PG"; include <PecheuxGraph_ILI9341_8bits.h> // Appel de la bibliothèque // Déclaration statique des instances, doit se faire en dehors du setup // Dans ce cas les boutons sont accessibles partout CheckZone boutonHaut(190, 90, 230, 130); // Bouton en haut CheckZone boutonCentre(190, 140, 230, 180); // Bouton au centre CheckZone boutonBas(190, 190, 230, 230); // Bouton en bas // Déclaration d'une fonction qui fera ce qu'il faut faire à chaque changement // Cette fonction ne doit pas avoir de paramètres et ne doit rien retourner // Le nom peut être quelconque void onSelectAction() // Action à faire quand on appuie sur un bouton { int y=getTouchY(); if (y<90) // On a touché sur le bouton du haut { if (boutonHaut.isSelected()) fillCircle(30, 110, 20, WHITE); // On s'occupe du premier bouton else fillCircle(30, 110, 20, BLACK); } else if (y>150) // On a touché sur le bouton du bas { if (boutonBas.isSelected()) fillCircle(30, 210, 20, WHITE); // Puis du troisième else fillCircle(30, 210, 20, BLACK); } else // on a donc forcément touché sur le bouton du milieu { // (Accolades inutiles pour le dernier cas) if (boutonCentre.isSelected()) fillCircle(30, 160, 20, WHITE); // Puis du deuxième else fillCircle(30, 160, 20, BLACK); } } void setup() { setGraphMode(PAYSAGE); // Initialisation de la carte rect(190, 90, 230, 130,GREEN); // Carré du haut rect(190, 140, 230, 180); // Carré au centre de l'écran rect(190, 190, 230, 230); // Carré du bas text(F("Appuyez sur un carré")); boutonHaut.onSelectFunction= // Fonction appelée si on active le bouton du haut de l'écran boutonCentre.onSelectFunction= // Fonction appelée si on active le bouton au milieu de l'écran boutonBas.onSelectFunction= // Fonction appelée si on active le bouton en bas de l'écran boutonHaut.onUnselectFunction= // Fonction appelée si on désactive le bouton du haut de l'écran boutonCentre.onUnselectFunction= // Fonction appelée si on désactive le bouton au milieu de l'écran boutonBas.onUnselectFunction=&onSelectAction; // Fonction appelée si on désactive le bouton en bas de l'écran } void loop() { scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans le loop }
Résultat:
Le fonctionnement est exactement le même que pour le premier exemple. C'est juste une histoire d'implantation.
Quatrième exemple: 3 boutons, loop() fait le travail
PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-923-CheckZone-loop\Exemple-923-CheckZone-loop.ino (dans votre fichier téléchargé):
// Mise en place de 3 boutons de type CheckZone (zone à cocher, pas de dessin // dans le bouton). Quand on appuie sur un bouton, un disque blanc montre son // activité // Version 4: // - Les boutons ont une définition statique // - Teste dans le loop sans utiliser onSelectFunction # $menu = ":PG"; include <PecheuxGraph_ILI9341_8bits.h> // Appel de la bibliothèque // Déclaration statique des instances, doit se faire en dehors du setup // Dans ce cas les boutons sont accessibles partout CheckZone boutonHaut(190, 90, 230, 130); // Bouton en haut CheckZone boutonCentre(190, 140, 230, 180); // Bouton au centre CheckZone boutonBas(190, 190, 230, 230); // Bouton en bas void setup() { setGraphMode(PAYSAGE); // Initialisation de la carte rect(190, 90, 230, 130,GREEN); // Carré du haut rect(190, 140, 230, 180); // Carré au centre de l'écran rect(190, 190, 230, 230); // Carré du bas text(F("Appuyez sur un carré")); } void loop() { scanEvent(); // Gestion des boutons et des horloges, d'habitude seul dans le loop // On va tester systématiquement l'état des boutons. Dans la vraie vie, on ne ferait le // test que si on en a besoin. Si c'est pour faire le test systématique, autant passer // par onSelectFunction. Ici c'est pour montrer que cela est possible. // Ici on surcharge beaucoup la boucle loop(), le dessin est fait systématiquement. // On manque des informations rapides sur les boutons if (boutonHaut.isSelected()) fillCircle(30, 110, 20, WHITE); // On s'occupe du premier bouton else fillCircle(30, 110, 20, BLACK); if (boutonBas.isSelected()) fillCircle(30, 210, 20, WHITE); // Puis du troisième else fillCircle(30, 210, 20, BLACK); if (boutonCentre.isSelected()) fillCircle(30, 160, 20, WHITE); // Puis du deuxième else fillCircle(30, 160, 20, BLACK); }
Résultat:
Le fonctionnement est exactement le même que pour le premier exemple. C'est juste une histoire d'implantation.
Cinquième exemple: 3 boutons, loop() fait le travail, avec mémorisation
PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-924-CheckZone-Memoire\Exemple-924-CheckZone-Memoire.ino (dans votre fichier téléchargé):
// Mise en place de 3 boutons de type CheckZone (zone à cocher, pas de dessin // dans le bouton). Quand on appuie sur un bouton, un disque blanc montre son // activité // Version 5: // - Les boutons ont une définition statique // - Teste dans le loop sans utiliser onSelectFunction // - On mémorise les actions faites pour ne pas surcharger loop() # $menu = ":PG"; include <PecheuxGraph_ILI9341_8bits.h> // Appel de la bibliothèque // Déclaration statique des instances, doit se faire en dehors du setup // Dans ce cas les boutons sont accessibles partout CheckZone boutonHaut(190, 90, 230, 130); // Bouton en haut CheckZone boutonCentre(190, 140, 230, 180); // Bouton au centre CheckZone boutonBas(190, 190, 230, 230); // Bouton en bas // Pour mémoriser les actions faites, on a recours à trois variables // qui vont permettre de savoir si un bouton a changé boolean ancienEtatBoutonHaut; // ancien état du bouton du haut boolean ancienEtatBoutonCentre; // ancien état du bouton du centre boolean ancienEtatBoutonBas; // ancien état du bouton du bas void setup() { setGraphMode(PAYSAGE); // Initialisation de la carte rect(190, 90, 230, 130,GREEN); // Carré du haut rect(190, 140, 230, 180); // Carré au centre de l'écran rect(190, 190, 230, 230); // Carré du bas text(F("Appuyez sur un carré")); } void loop() { scanEvent(); // Gestion des boutons et des horloges, d'habitude seul dans le loop // On va tester systématiquement l'état des boutons pour savoir si l'un d'eux a changé. // Si c'est le cas, on agit. // Ici on surcharge peu la boucle loop(), le dessin est fait que si nécessaire. if (boutonHaut.isSelected()!=ancienEtatBoutonHaut) { // Le bouton haut a changé d'état, on le redessine if (boutonHaut.isSelected()) fillCircle(30, 110, 20, WHITE); // On s'occupe du premier bouton else fillCircle(30, 110, 20, BLACK); ancienEtatBoutonHaut=boutonHaut.isSelected(); // Et on met à jour la mémoire } if (boutonCentre.isSelected()!=ancienEtatBoutonCentre) { // Le bouton du centre a changé d'état, on le redessine if (boutonCentre.isSelected()) fillCircle(30, 160, 20, WHITE); // Puis du troisième else fillCircle(30, 160, 20, BLACK); ancienEtatBoutonCentre=boutonCentre.isSelected(); // Et on met à jour la mémoire } if (boutonBas.isSelected()!=ancienEtatBoutonBas) { // Le bouton bas a changé d'état, on le redessine if (boutonBas.isSelected()) fillCircle(30, 210, 20, WHITE); // Puis du deuxième else fillCircle(30, 210, 20, BLACK); ancienEtatBoutonBas=boutonBas.isSelected(); // Et on met à jour la mémoire } }
Résultat:
Le fonctionnement est exactement le même que pour le premier exemple. C'est juste une histoire d'implantation.
Sixième exemple: 3 boutons, 3 fonctions externes
PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-925-Maison-CheckZone\Exemple-925-Maison-CheckZone.ino (dans votre fichier téléchargé):
// L'intérieur d'une maison est dessinée. Deux boutons de type CheckZone // permettent d'allumer la lumière. Ce sont des va et vient (boutons à 2 // positions comme les cases à cocher) # $menu = ":PG"; include <PecheuxGraph_ILI9341_8bits.h> // Déclaration statique des instances, doit se faire en dehors du setup // Dans ce cas les boutons sont accessibles partout CheckZone bouton1(186, 124, 212, 152); // Définit une zone cliquable à droite CheckZone bouton2(8, 124, 34, 152); // Définit une zone cliquable à droite // Déclaration d'une fonction qui fait ce qu'il faut faire à chaque changement // Cette fonction ne doit pas avoir de paramètres et ne doit rien retourner // Le nom peut être quelconque // Cette fonction allume ou éteint la lampe. Elle est allumée si un seul des // deux boutons est actif. C'est pour cela qu'on utilise le ou-exclusif ^ void lampe() { fill(160, 30+1, bouton1.isSelected() ^ bouton2.isSelected() ? YELLOW : BLACK); // La lampe copie l'état des boutons } void setup() { bouton1.onSelectFunction = &lampe; // Change l'état de la lampe si on active le bouton de droite bouton2.onSelectFunction = &lampe; // Change l'état de la lampe si on active le bouton de gauche bouton1.onUnselectFunction = &lampe; // Change l'état de la lampe si on désactive le bouton de droite bouton2.onUnselectFunction = &lampe; // Change l'état de la lampe si on désactive le bouton de gauche setGraphMode(PAYSAGE); // Initialisation // Consigne setTextCursor(10, 200); text(F("Appuyez sur un bouton de\n chaque côté de la fenêtre")); maison(1,1); // avec 2 boutons } void loop() { scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans le loop }
Résultat:

Côté technique
En fait CheckZone ne fait pas grand chose, car c'est le gestionnaire scanEvent() qui vient demander les propriétés de CheckZone et qui calcule si il est sélectionné ou pas. C'est aussi le gestionnaire qui appelle onSelect() et onSelectFunction si le contrôle vient d'être choisi ou onClac() et onClacFunction si le contrôle vient d'être relâché. Le rôle de CheckZone se borne à initialiser les valeurs lors de sa déclaration, et à répondre aux événements clic ou clac.
On ne stocke pas les coordonnées complètes car il faut un entier pour le stockage. La moité de la valeur tient dans un byte, et au niveau de la précision cela suffit. Ainsi chaque bouton économise 4 octets, et les tests de limites portent sur des octets, ce qui est mieux.