I. Résumé▲
Afficher une barre de progression est très facile dans 4D. Votre process courant ne sera pas toujours à même de mettre à jour les barres de progression lui-même et c'est pourquoi un nouveau process sera parfois requis. Nous allons voir comment afficher un thermomètre, aborder comment communiquer entre les process presque sans utiliser de variables interprocess et comment afficher plusieurs barres de progression dans un même dialogue.
II. Utiliser les thermomètres, pourquoi ?▲
Lorsque votre base de données exécute des traitements longs, il est d'usage courant d'afficher un thermomètre, une barre de progression qui permet à l'utilisateur de connaître l'état d'avancement de ses traitements. Comment faire cela dans 4D ?
Si vous avez utilisé la palette d'outils lorsque vous éditez un formulaire, vous avez remarqué que l'on peut créer un objet thermomètre et le placer sur un formulaire. Vous pouvez commencer par créer un formulaire et dessiner un thermomètre dans le but d'afficher une progression des tâches. Dans beaucoup d'interfaces, vous allez sélectionner une ligne de menu ou cliquez sur un objet comme un bouton dans la fenêtre courante. Si la méthode lancée exécute un traitement long, c'est à ce moment-là que vous souhaiterez afficher le thermomètre ; pour cela, vous devez créer une nouvelle fenêtre et mettre à jour le thermomètre étape par étape. Mais alors, vous constaterez que le thermomètre ne se met pas à jour, pourquoi ?
Le problème est que le process courant est déjà occupé à exécuter ce long traitement et les fenêtres sont mises à jour quand les process sont inactifs et attendent un événement formulaire. C'est pourquoi vous ne pouvez voir le thermomètre progresser dans la fenêtre. Alors, que peut-on faire ?
Une solution très compliquée consiste à afficher le dialogue du thermomètre et à créer un nouveau process qui exécutera le long traitement. Si cette solution est faisable, elle sera très complexe, spécialement si le process a besoin d'accéder à des variables existantes ou des sélections courantes. Ainsi, une autre solution serait de créer un nouveau process pour afficher le thermomètre. Le process créé est local et affichera le dialogue de progression. C'est la solution que nous allons décrire.
La question suivante est : comment mettre à jour le thermomètre ? Une première technique serait d'utiliser des variables interprocess. L'objet thermomètre serait alors une variable interprocess. Ses valeurs iraient de 0 à 100. Dans votre process courant, vous augmentez automatiquement la valeur de la variable et utilisez la commande APPELER PROCESS(-1) pour redessiner cette variable.
APPELER PROCESS est normalement utilisé pour envoyer un signal à un autre process affichant un formulaire (l'événement formulaire Sur appel extérieur est exécuté), mais cela nécessite un numéro de process et - 1 n'est pas un numéro de process valide. Dans le cas présent, APPELER PROCESS (-1) force la mise à jour de tous les dialogues qui affiche une variable interprocess. Il n'existe pas de solution parfaite si vous avez à afficher plusieurs barres de progression, et l'on ne peut utiliser une variable interprocess unique.
Cela signifie que l'objet thermomètre doit être une variable globale. Mettre à jour une variable globale d'un process dans un autre process est assez aisé. Vous pouvez utiliser la commande VARIABLE VERS VARIABLE ou ECRIRE VARIABLE PROCESS. Cette technique sera illustrée dans la méthode M_Test1 et vous pourrez voir que le thermomètre sera mis à jour.
Trois nouveaux problèmes surviennent.
Le premier problème est que le thermomètre est un objet 4D et est par défaut saisissable. Durant le process, l'utilisateur peut manipuler la valeur courante du thermomètre en l'augmentant ou en la diminuant. Nous devons d'abord définir le thermomètre comme non saisissable.
Le second problème est que, une fois la variable mise à jour, le thermomètre ne le sera peut-être pas. La valeur mise à jour, nous devons aussi dire au dialogue de mettre à jour l'affichage. Deux techniques sont possibles. La première consiste à utiliser l'événement Sur minuteur. À chaque seconde, le dialogue exécute l'événement Sur minuteur et nous pouvons mettre à jour la fenêtre en exécutant la commande REDESSINER FENETRE. Ceci requiert beaucoup de temps CPU simplement pour mettre à jour un thermomètre tous les 60 ticks. Considérant que la valeur du thermomètre peut ne pas changer pendant un moment, cela fait perdre beaucoup de temps CPU. La seconde solution serait de mettre à jour la fenêtre sur demande. Comment ? En utilisant la commande APPELER PROCESS. Ces deux techniques seront développées dans la méthode M_TEST1.
Le troisième problème est qu'une fois que le thermomètre a atteint 100 %, nous devons fermer le dialogue. Nous pouvons utiliser une variable globale de type Booléen qui sera testée, et si elle est à Vrai, nous fermons le dialogue, ou nous pouvons utiliser la variable thermomètre. Si sa valeur est supérieure à 100, nous fermons le dialogue.
III. La méthode M_Test1▲
Décrivons maintenant ces techniques avec un exemple concret. Si nous exécutons cette méthode (vous pouvez aussi sélectionner la ligne Exemple 1 en Menus Créés), nous voyons 4 thermomètres différents qui s'affichent. Comment cela fonctionne-t-il ? Tout d'abord, examinons la méthode.
Nous pouvons voir que nous appelons la méthode nommée M_Thermo_Create avec quelques paramètres :
- le premier paramètre est le type de la fenêtre que nous utiliserons pour la fenêtre Thermomètre ;
- les deux paramètres suivants sont les coordonnées de la fenêtre. -1 pour ces deux paramètres signifie que le dialogue sera centré dans la fenêtre de l'application ;
- le quatrième paramètre est le titre de la fenêtre. Un titre sera affiché si le type de la fenêtre le permet ;
- le cinquième paramètre est une rapide description de ce qui sera affiché dans le dialogue Thermomètre ;
-
le sixième paramètre définit quel système nous utilisons. Nous disposons de 4 systèmes :
- le premier système est l'utilisation du thermomètre et du système Sur appel extérieur (valeur 1),
- le second système et l'utilisation de l'événement Sur minuteur et mise à jour du thermomètre tous les 60 ticks (valeur 2),
- les troisième et quatrième systèmes sont identiques pour les deux premières options (soit Sur appel extérieur, soit Sur minuteur) excepté qu'une image peut être utilisée à la place d'un objet thermomètre (valeur 3 et 4). Pourquoi une image ? Vous pourriez vouloir afficher votre propre thermomètre ou utiliser une image particulière. Dans ce cas vous devez définir votre image au format Tronquée.
Dans notre exemple, l'image Thermo1 de la bibliothèque d'image est utilisée de façon répétée pour simuler un long thermomètre.
M_Thermo_Create utilise un Sémaphore pour mettre à jour un tableau interprocess. Le numéro du process du dialogue Thermomètre est stocké dans ce tableau. Cette étape n'est pas vraiment nécessaire pour le thermomètre lui-même, mais peut être utile pour les mises à jour. Nous pouvons voir que dans la méthode M_TEST1, nous appelons la méthode M_Thermo_Update avec l'ID du process du dialogue Thermomètre et la nouvelle valeur pour ce thermomètre. Comme vous pouvez voir, cette méthode utilise un ECRIRE VARIABLE PROCESS basée sur l'ID du process fournit. Mais si l'ID du process n'est pas valide ? Ceci juste pour rappeler combien il est dangereux de pouvoir modifier des variables dans d'autres process. Ces commandes puissantes impliquent que vous les utilisiez avec précaution. Vous devez toujours vérifier que vous allez mettre à jour le bon process et non pas mettre à jour des variables dans des process au hasard.
La méthode M_Thermo_Display est la méthode qui crée la fenêtre du thermomètre, basée sur le formulaire [Table1]ThermoDialog. Cette méthode retrouve les paramètres fournis avec l'appel de M_Thermo_Create et les assigne aux variables appropriées dans le formulaire ou au titre de la fenêtre. Si vous vérifiez maintenant la méthode formulaire, vous pouvez voir que, dans l'événement Sur chargement, nous déplaçons les objets (image et objet thermomètre) aux coordonnées appropriées et mettons en place l'événement Sur minuteur si nécessaire (paramètre 2 ou 4).
Sur l'événement Sur Minuteur ou Sur appel extérieur, vous pouvez augmenter la taille de l'image si nécessaire et redessiner la fenêtre. Redessiner la fenêtre est obligatoire si vous voulez que vos objets thermomètres soient mis à jour.
Comme vous pouvez le voir, cinq méthodes suffisent pour implémenter les thermomètres dans votre base :
- M_Thermo_Initvariables : définit quelques valeurs par défaut et initialise le tableau qui manipule les process courants ;
- M_Thermo_Create : lance les process et met à jour le tableau des ID (identifiants) des process ;
- M_Thermo_Display : affiche la fenêtre du formulaire ;
- M_Thermo_Update : met à jour la valeur courante du thermomètre ;
- M_Thermo_CloseBox : si la fenêtre possède une case de fermeture, mise à jour des tableaux.
IV. La méthode M_Test2▲
Créer une interface qui montre la progression, c'est bien joli, mais cela peut ralentir votre application. Créer un process et mettre à jour son interface coûte du temps CPU. Ce peut être une très mauvaise idée de lancer de nombreux process et que chacun affiche une barre de progression. Dans 4D, une barre de progression est habituellement affichée quand 20 secondes se sont écoulées depuis le début du process. Vous pouvez choisir la même limite pour votre base. Mais qu'en est-il si votre process peut effectuer plusieurs tâches en même temps ? Affiché quatre thermomètres différents signifie quatre process séparés. Il pourrait être intéressant d'afficher seulement une fenêtre avec quatre barres de progression.
C'est ce que vous pouvez tester avec l'exemple 2 en Menus Créés. Vous avez un tableau Texte de 20 éléments et vous voulez créer un dialogue qui puisse afficher quatre thermomètres. Ces quatre thermomètres seront référencés par les tableaux at_ItemInProgress et al_ItemInProgress. Ces deux tableaux contiendront les messages et les valeurs courantes des thermomètres.
Toutes les valeurs seront initialisées à -1, ce qui signifie qu'un numéro est disponible pour un nouveau thermomètre. L'appel à la méthode M_ThermoMulti_InsertItem sert à vérifier si un numéro est disponible. Si c'est le cas, nous utiliserons ce numéro pour manipuler notre nouveau thermomètre. Sinon, nous attendrons qu'un numéro soit disponible.
L'appel à cette méthode retourne un ID, l'ID dans le tableau al_ItemInProgress où nous avons besoin de stocker les valeurs du thermomètre associé. La méthode M_ThermoMulti_Create retourne l'ID du process du dialogue Thermomètre. Nous fournirons cet ID à la méthode M_ThermoMulti_Update pour mettre à jour les thermomètres. La méthode principale boucle jusqu'à ce que les 20 éléments soient traités et jusqu'à ce qu'il n'y ait plus de thermomètres à afficher (information fournie par la variable nb_ItemInProgress). Si vous n'avez pas d'autres thermomètres à afficher, vous pouvez les garder pour un usage futur, ainsi cacher le process et le ramener au premier plan lorsque vous en avez besoin. Dans notre cas, nous avons terminé, nous pouvons juste fermer la fenêtre en utilisant la méthode M_ThermoMulti_CloseWindow. Cette méthode utilisera la seconde méthode précédemment définie. Nous allons mettre à Vrai la variable vThermoMulti_Close définie dans la fenêtre Thermomètre en utilisant la commande VARIABLE VERS VARIABLE. Puis nous dirons à ce process de vérifier la variable et de fermer la fenêtre en utilisant la commande APPELER PROCESS.
Le dialogue Thermomètre est affiché par la méthode M_ThermoMulti_Display. Une fenêtre est créée, basée sur une valeur indiquée en paramètre et un DIALOGUE est exécuté en conjonction avec le formulaire ThermoMultiDialog.
Comme vous pouvez le voir, il y a 5 thermomètres, des variables messages et des variables « indicateur ». Tous ces objets ont un nom d'objet spécifique qui sera utilisé avec la commande DEPLACER OBJET. Au chargement du formulaire, nous déplaçons tout hors de la zone visible. Lorsqu'un thermomètre a besoin d'être affiché, nous insérons ses valeurs dans les deux tableaux comme défini précédemment et nous appelons la méthode M_ThermoMulti_Update.
Cette méthode exécute un APPELER PROCESS qui déclenche un événement Sur appel extérieur dans le dialogue Thermomètre. Si nous revenons à la méthode formulaire, nous pouvons voir que sur l'événement Sur appel extérieur, la variable vThermoMulti_CloseWindow est vérifiée et nous pouvons fermer la fenêtre. D'une autre manière, cela signifie que l'appel était fait pour mettre à jour les valeurs du thermomètre. La technique est très simple. Nous avons ces deux tableaux avec de nouvelles valeurs. Nous analysons les valeurs et voyons si elles sont différentes de -1. Si c'est le cas, un thermomètre sera affiché. Nous pouvons avoir à afficher 2 ou 3 thermomètres et devons nous assurer que les thermomètres ne seront pas déplacés au même endroit. C'est pourquoi il y a un compteur, $ind, qui nous indiquera combien de thermomètres ont déjà été affichés. Nous avons « hard codé » l'espace requis pour afficher le thermomètre, ses messages et message de progression d'une hauteur totale de 90 pixels. Nous pouvons utiliser ce compteur et la hauteur par défaut pour établir où le prochain thermomètre devrait être affiché. Une fois que tous les thermomètres ont été affichés, nous retaillons la fenêtre pour afficher tous les thermomètres courants. Les utilisateurs peuvent déplacer la fenêtre sur l'écran ; c'est pourquoi nous chargeons les coordonnées courantes et retaillons juste la hauteur de la fenêtre.
Quatre méthodes sont nécessaires pour afficher le dialogue Thermomètre capable d'afficher les cinq barres de progression dans le même dialogue :
- M_ThermoMulti_Create : crée la fenêtre du thermomètre ;
- M_ThermoMulti_Display : affiche le dialogue du thermomètre ;
- M_ThermoMulti_InsertItem : vérifie si un numéro est disponible pour un nouveau thermomètre ;
- M_ThermoMulti_Updates : met à jour les tableaux utilisés pour afficher ces thermomètres ;
- M_ThermoMulti_CloseWindow : laisse la fenêtre du thermomètre fermer le dialogue par lui-même.
V. Conclusion▲
Afficher une barre de progression est très facile dans 4D. Votre process courant ne sera pas toujours à même de mettre à jour les barres de progression lui-même et c'est pourquoi un nouveau process sera parfois requis. Nous avons vu comment afficher un thermomètre, abordé comment communiquer entre les process presque sans utiliser de variables interprocess et comment afficher plusieurs barres de progression dans un même dialogue.