Cours Apl 11 :
Introduction à la gestion des écrans |
|
Dyalog Apl vous permet de créer les écrans de 2 manières compatibles : - à la souris, comme dans la plupart des langages (via le ws wdesign), - en écrivant des fonctions qui construisent et/ou modifient les écrans. C'est cette voie que nous allons explorer.
Quelques notions préliminaires - Objet : on appelle objet une fenêtre, un bouton, une zone de liste, ... - Propriété : une propriété défini les caractéristiques d'un objet telles que sa taille, sa couleur, son contenu, son libellé, son nom, ... -
Evènement : Il peut arriver diverses choses à un objet du fait de
l'utilisateur du programme.
A quoi servent les évènements ?
Lorsqu'un évènement précis se produit, on veut déclencher une action. - Méthode : On peut assimiler une méthode à une fonction de l'objet auquel elle appartient. Par exemple, dans le cas de l'objet Grid (tableur Apl), il existe une méthode AddRow qui permet d'ajouter des lignes. Une méthode est appelée par un programme alors qu'un évènement résulte généralement d'une action de l'utilisateur.
Premiers objets et propriétés : L'objet de base est la fenêtre : Form Elle a un certain nombre de propriétés dont le type de l'objet, un libellé, un emplacement et une taille. Pour créer un objet window, on utilise la fonction système ŒWC (window create).
L'argument gauche est le nom que portera l'objet et l'argument droit
contient les propriétés de l'objet. Maintenant passons à l'action. Nous allons créer notre première fenêtre qui s'appellera F1. 'F1' ŒWC 'Form' ('Caption' 'Multiplication')('Size' 50 50) Vous trouverez une nouvelle icône dans la barre des tâches. Si vous cliquez dessus, vous verrez apparaître une fenêtre vide, dont le titre sera "Multiplication", occupant la moitié de l'écran.
Ajoutons deux zones de saisie avec leurs libellés à cet écran. D'abord, le libellé : 'F1.L1' ŒWC 'Label' 'Série de nombres' ('Posn' 10 5)('Size' « 25) - A chaque fois qu'on crée un objet, on doit respecter la syntaxe suivante : 'objet_père.nouvel objet' ŒWC 'Type d'objet' ('nom_propriété 1' valeur(s)_propriété 1) ('nom_propriété 2' valeur(s)_propriété 2) - Les propriétés ont toutes un emplacement par défaut. Ainsi, on peut directement indiquer la valeur d'une propriété sans en mentionner le nom, si on la place au bon endroit. -
Type d'objet -
'Label' signifie que F1.L1 est une étiquette. - 'Série de nombres' est le texte affiché. Le nom de cette propriété est 'Caption'. Pour un Label c'est toujours la deuxième propriété définie. Aussi, si on la met à cet endroit, il n'est pas obligatoire de mentionner le nom de la propriété définie. -
'Posn' indique la position du coin supérieur gauche de l'objet par
rapport au coin supérieur gauche de l'objet père. Par défaut ces
coordonnées sont exprimées en pourcentage de la taille de l'objet père. -
'Size' défini la taille de l'objet. ('Size' « 25) signifie qu'on laisse Apl choisir la hauteur la plus appropriée et qu'on force la largeur à 25% de celle de F1.
Ajoutons maintenant le champ de saisie de la série de nombres : 'F1.S1' ŒWC 'Edit' ('Posn' 10 40)('Size' « 50)
Nouveau label et nouveau champ :
'F1.L2' ŒWC 'Label' 'Coefficient : ' ('Posn' 30 5)('Size' « 25)
Affichage du résultat du calcul :
'F1.L3' ŒWC 'Label' 'Résultat : ' ('Posn' 50 5)('Size' «
25)
Bouton de lancement du calcul : 'F1.B1' ŒWC 'Button' 'Calculer' ('Posn' 80 «)('Size' « 50)
Une fois tout ça saisi, vous devez avoir à l'écran votre nouvelle fenêtre :
En entrant ce code, vous avez créé un nouvel objet : F1 Si vous tapez ŒNL 9, Apl vous répondra : F1 ŒNL signifie 'Name List'. Il rend la liste des noms correspondant à la ou les classes données en argument droit. ŒNL 2 rend la liste des variables et ŒNL 3 la liste des fonctions. ŒNL 9 rend la liste des namespaces et des objets graphiques.
Pour en savoir plus : - aide en ligne - ŒNC : réciproque de ŒNL, rend la classe de l'objet nommé en argument droit.
Pour l'instant l'écran existe mais il ne fait rien. Effacez F1 en tapant : )erase F1 puis créez la fonction Mulvec, localisez F1 et reprenez les lignes de définition de l'écran dans la fonction. Si vous lancez la fonction, il ne se passe rien, vous ne voyez rien à l’écran. C'est normal : l'écran est créé, mais comme il est localisé dans la fonction, il est détruit, dès qu'on en sort. Pour que l'écran soit actif, vous devez "donner la main" à Windows. C'est la fonction ŒDQ qui s'en charge. Elle active l'objet dont le nom est mentionné en argument droit. Ajoutez cette ligne dans votre fonction et relancez-la : ŒDQ 'F1'
Listing de la fonction :
Mulvec;F1;CR
L'écran s'affiche, on peut même saisir des valeurs mais pour l'instant aucun calcul ne s'effectue. Pour quitter votre nouvel écran et revenir à APL, fermez la fenêtre en cliquant sur la croix en haut à droite.
C'est ici qu'interviennent les évènements. Quand l'évènement "clic sur le bouton calculer" se produit, on veut que la multiplication soit effectuée et que le résultat soit affiché dans F1.S3 On a le choix entre 2 méthodes : - soit on analyse le résultat du ŒDQ dans la fonction Mulvec pour voir si le calcul a été demandé - soit on appelle une fonction de traitement spécifique (fonction callback). Nous allons d'abord explorer cette voie.
Créez la fonction Mulvec_cal Elle admet comme argument droit le compte rendu de l'événement ayant occasionné son appel. Toute fonction callback possède au moins cet argument car APL l’appelle systématiquement en le lui passant et il est souvent utilisé, comme nous le verrons par la suite. Entrez ces lignes dans la fonction : Mulvec_cal d F1.S3.Text„•(–F1.S1.Text)×(–F1.S2.Text) La fonction exécute (–), exécute la chaîne de caractères qui lui est passée en argument droit. Dans le cas d’une chaîne de caractères contenant uniquement des numériques, elle rend un ou plusieurs nombres (plusieurs si ils sont séparés par des espaces ou des virgules) et la fonction format (•) convertit un ou plusieurs nombres en chaîne de caractères. Le contenu d'un champ texte correspond à sa propriété 'Text' et ne peut être qu'une chaîne de caractères, même si elle n'est constituée que de chiffres. C'est pourquoi on formate le résultat du calcul avant de le mettre dans F1.S3. De même, on ne peut multiplier que des chiffres, c'est pourquoi on numérise le contenu des champs S1 et S2.
Branchons maintenant notre fonction de calcul. Nous devons donc dire à APL que quand le bouton B1 est actionné, on doit appeler la fonction Mulvec_cal. Pour ce faire, nous allons modifier la ligne de définition du bouton comme suit : 'F1.B1'ŒWC'Button' 'Calculer'('Posn' 80 «)('Size'« 50)('Event' 'Select' 'Mulvec_cal')
- Event
signifie qu’on défini la propriété Evènement.
Essayez à nouveau votre fonction. C'est un traitement conditionnel dont l'idée est : "si ça se passe bien, je fais ci, sinon je fais ça." Nouveau texte de la fonction : Mulvec_cal
d Pour en savoir plus sur le :Trap consultez l'aide en ligne. On gère également les erreurs avec le ŒTrap. Réessayez en saisissant des valeurs incorrectes.
Nous allons maintenant voir comment gérer les événements sans utiliser de fonction callback.
Commençons par remplacer la zone de saisie F1.S2 par un objet Spinner. Nous allons également demander à Apl de reprendre la main lorsqu'on clique sur une des flèches pour modifier la valeur du spinner afin de recalculer immédiatement le résultat avec le nouveau coefficient. Remplacez la définition de F1.S2 par : 'F1.S2'ŒWC'Spinner'('Posn' 30 40)('Size'« 40)('Event' 'Spin' 1)('Limits' ¯100 100) Remplacez également la dernière ligne de la fonction Mulvec par les suivantes :
ET_AFF:CR„ŒDQ 'F1' ET_AFF: est une étiquette qui indique une ligne de la fonction. :If 0¬½CR marque le début d'un bloc d'instructions exécutées uniquement si la taille de CR n'est pas nulle. En effet, si on ferme la fenêtre en cliquant sur la croix en haut à droite, CR reçoit un vecteur vide. Si le test est concluant, on met le 3ème élément de CR (nouvelle valeur) dans F1.S2, on refait un calcul en appelant Mulvec_cal '' (l'argument n'a aucune importance puisqu'il n'est pas exploité par la fonction), et avec …ET_AFF on redonne la main à Windows. Dans le respect des règles d’hygiène des développeurs pas trop cochons, ajoutez CR à votre liste de variables locales. Testez votre fonction. Au cas où quelque chose ne fonctionnerait pas correctement, le texte complet de la fonction est :
Mulvec;F1;CR Pour en savoir plus sur les objets graphiques mis à votre disposition dans Dyalog Apl, il existe 2 tutoriels très riches : - Wtutor - Wtutor95 Chargez les et explorez tout, c'est simple, efficace et vraiment beau. Pour les passionnés de graphiques, allez faire un tour du coté du workspace Rain. Sinon, il y a toujours l'aide en ligne. Travaux pratiques :
0. Chargez votre Ws de travaux pratiques : )load c:\Mes documents\pratique-apl Nous allons continuer à travailler sur la matrice du personnel mais cette fois à travers une interface graphique que nous allons créer comme ci-dessous :
Pour tous les nouveaux objets, l'aide en ligne et les tutoriels sont là.
1. Vos objectifs sont les suivants : - Créez une fonction "GestPerso" qui va commencer par créer un nouvel écran dont le libellé sera "Personnel MyStyle Ltd" - Afficher la matrice du personnel dans un Grid avec la possibilité d'en modifier le contenu, de supprimer et ajouter des personnes. Intitulés de lignes :
- nom - Afficher dans un autre grid en dessous les statistiques suivantes :
- l'effectif masculin, féminin et total Ces données devront être rafraîchies au fur et à mesure des saisies opérées dans l'autre grid. - Ajoutez 2 boutons en bas de l'écran : - Sauver et quitter : Met à jour la variable Perso et ferme la fonction, donc l'écran puisque vous l'aurez localisé dans la fonction. - Quitter sans sauver.
2. Ajoutez 2 nouvelles zones de saisie numériques avec leurs intitulés : -
Pourcentage de variation - Ajoutez un bouton "Lancer Simulation", qui modifie tous les éléments en fonction du % de variation et du plafond (dont la saisie est facultative). Attention, les données de la simulation ne peuvent pas être sauvegardée. - Ajoutez un bouton "Fermer Simulation", qui remet les données réelles à l'écran. Solutions :
1. Vos objectifs sont les suivants : - Créez une fonction "GestPerso" qui va commencer par créer un nouvel écran dont le libellé sera "Personnel MyStyle Ltd"
GestPerso;F1
- Afficher la matrice du personnel dans un Grid avec la possibilité d'en modifier le contenu, de supprimer et ajouter des personnes. Intitulés de lignes :
- nom
'F1.G1'ŒWC'Grid'('Posn' 0 0)('Size' 150
400)('Values'Perso) Pour modifier le contenu du Grid, il faut créer des champs edit ou autres objets appropriés. On procède en 2 temps : - on crée d'abord les objets d'édition, fils du Grid : 'Form1.Grid1.Edit1' ŒWC 'Edit'
- on les affecte aux cellules adéquates via la propriété CellTypes :
'Form1.Grid1'
ŒWS 'CellTypes'((½Form1.Grid1)½1)
Commençons par créer nos éditeurs : - Pour la première ligne, un champ edit alphabétique suffira : 'F1.G1.E1'ŒWC'Edit' ('FieldType' 'Char')
- Pour la deuxième, une combo avec les choix 'H' et 'M' : 'F1.G1.C1'ŒWC 'Combo' ('Style' 'Drop')('Items' (2 1½'HF'))
- Pour les deuxième et troisième lignes on utilisera un éditeur acceptant uniquement des nombres : 'F1.G1.E2'ŒWC'Edit' ('FieldType' 'Numeric')
A présent, il ne reste plus qu'à associer les bons éditeurs aux bonnes cellules. Nous avons 3 éditeurs. Considérons que F1.G1.E1 sera utilisé par des cellules de type 1, F1.G1.C1 par des cellules de type 2 et F1.G1.E2 par des cellules de type 3.
F1.G1.CellTypes„(½F1.G1.Values)½3
Maintenant, déclarons les objets d'édition dans le bon ordre (F1.G1.E1 pour les cellules de type 1, F1.G1.C1 pour les cellules de type 2 et F1.G1.E2 pour les cellules de type 3) : F1.G1.Input„'F1.G1.E1' 'F1.G1.C1' 'F1.G1.E2'
Afin de voir ce que donne cet écran, ajoutez ŒDQ'F1' et lancez la fonction. Listing :
GestPerso;F1;tmp
- Pour ajouter des personnes, il faut déplacer le curseur à droite, au delà de la dernière colonne. Par défaut le grid n'autorise pas ceci. Il faut modifier sa propriété AutoExpand (booléen de 2 positions : lignes, colonnes) et lui mettre 0 1 afin qu'il autorise l'ajout de colonnes mais pas celui de lignes : F1.G1.AutoExpand„0 1
- Pour supprimer les colonnes, l'utilisateur cliquera sur une entête de colonne, faisant apparaître un menu contextuel lui demandant si il veut simplement sélectionner la colonne entière ou si il veut la supprimer. Nous allons donc commencer par créer un menu directement rattaché à F1 :
'F1.M1'ŒWC'Menu'
Ensuite, nous allons lier l'affichage de ce menu à un clic sur un entête de colonne : 'F1.G1'ŒWS('Event' 'CellDown' 'GestPerso_sel')
Le menu ne doit être activé que si on a cliqué sur une entête de colonne et pas ailleurs dans le grid. C'est pourquoi la fonction callback GestPerso_sel commence par tester le compte-rendu d'événement qu'elle reçoit automatiquement en argument droit. Texte de la fonction :
GestPerso_sel d;cr
- Afficher dans un autre grid en dessous les statistiques suivantes :
- l'effectif masculin, féminin et total Ces données devront être rafraîchies au fur et à mesure des saisies opérées dans l'autre grid. Ajoutons la définition du nouveau grid dans GestPerso :
'F1.LS'ŒWC'Label'
'Statistiques'('Posn' 170 «) Pour mettre les données de G2 à jour, nous allons utiliser une fonction GestPerso_Stats qui sera utilisée lorsque l'événement CellChanged se produira dans G1. Nous allons également l'appeler une première fois afin de remplir G2 avec des vraies valeurs. Définition de GestPerso_Stats :
GestPerso_Stats d;tmp;sexe On
commence par créer un vecteur des sexes avec les 3 possibilités
indiquées en commentaire.
© Homme=1, femme=2, autre=0
Pour le calcul suivant, on s'assure que les montants récupérés existent
bien. En effet, pendant la création d'une nouvelle personne le salaire
n'est pas encore connu.
© Masse salariale Le principe est le même que précédemment sauf qu'au lieu de sommer, on calcule la moyenne arrondie à l'entier le plus proche.
© Salaires Moyens
Il faut également modifier la définition de F1.G1 afin qu'il appelle GestPerso_Stats quand une cellule est modifiée : 'F1.G1'ŒWS('Event' 'CellChanged' 'GestPerso_Stats') Il faut aussi faire un premier appel à GestPerso_Stats immédiatement après la définition de F1.G2 : GestPerso_Stats 1
- Ajoutez 2 boutons en bas de l'écran : - Sauver et quitter : Met à jour la variable Perso et ferme la fonction, donc l'écran puisque vous l'aurez localisé dans la fonction. - Quitter sans sauver. On ajoute les lignes suivantes afin de créer 2 boutons qui rendront la main à Apl en sortie du ŒDQ.
'F1.BSQ'ŒWC'Button' 'Sauver et Quitter'('Posn' 90
10)('Size'« 35)('Event' 'Select' 1)
Si
tmp est vide ou si c'est F1.BSQ qui a été actionné, on sort sans rien
faire.
2. Ajoutez 2 nouvelles zones de saisie numériques avec leurs intitulés :
- Pourcentage de variation
'F1.LS2'ŒWC'Label' 'Pourcentage de Variation :'('Posn'
310 10)('Size'« 150)
- Ajoutez un bouton "Lancer Simulation", qui modifie tous
les éléments en fonction du % de variation et du plafond (dont la saisie
est facultative). - Ajoutez un bouton "Fermer Simulation", qui remet les données réelles à l'écran. Nous avons besoin d'une nouvelle variable locale intitulée PersoLoc qui stockera les valeurs réelles du grid pendant les simulations.
GestPerso;F1;tmp;PersoLoc
Définition des 2 boutons :
'F1.BC'ŒWC'Button'
'Lancer simulation'('Posn' 310 300)('Size'« 100)('Event' 'Select' 'GestPerso_simu')
Texte de la fonction GestPerso_simu :
GestPerso_simu d;Augm
Listing de la fonction GestPerso :
GestPerso;F1;tmp;PersoLoc |
|