ScNat
Ref Gen

Réflexions générales sur les techniques de programmation

Je suis toujours un peu confus quand je bâtis un programme qui possède une importante interface usager car j’ai plus souvent écrit des programmes de number crunching avec un fichier en output et des résultats à la fin.

Un programme avec GUI passera la plus grande partie de son temps à observer l’utilisateur et à executer cette boucle: l’usager a-t-il appuyé sur une touche de clavier? Si oui, faire quelque chose, sinon attendre un peu et se reposer la question. Avec une interface graphique ce sera: l’usager a-t-il appuyé sur le bouton? Si oui, dessiner un bouton enfoncé et faire quelque chose, sinon attendre un peu et se reposer la question pour un autre bouton.

L’ensemble du parcours que fera l’application pour interroger les widgets est essentiellement invisible au programmeur et s’appelle the event loop. Cette boucle est gérée de façon transparente par la librairie GUI utilisée. Les éléments les plus visibles de la librairie dans le code sont les initialisations de widgets (boutons, zones de texte, sliders) et souvent en dernière ligne de code, l’entrée de la event loop, ressemblant à application.run(). C’est à cet endroit que le programmeur ‘perd’ le contrôle de son programme et le remet à la librairie.

Comment contrôler alors les diverses fonctionnalités prévues par le programme? Elles s’exécuteront lors des activations des widgets, ils possèdent tous un paramètre obligatoirement initialisé par le programmeur: les callback functions, une par widget. Cette fonction doit être écrite par le programmeur et correspond au ‘quelque chose à faire’ dans le paragraphe précédent.

La difficulté résidera à transmettre entre les diverse composantes du programmes les états modifiés par les interaction GUI en évitant absolument l’utilisation de variables globales.

Cette difficulté se résout en transmettant lors de l’initialisation des widgets non seulement un pointeur vers une fct callback mais également un pointeur vers un objet mutable(ou une variable) sur lequel la fonction pourra agir en modifiant certaines variables d’instances de l’objet.

Pour notre projet un objet sonde sera créé et la relation de calibration sera une de ses variable d’instance (ivar) avec une methode correspondante la_sonde.set_calib_rel(a_rel). cf la doc pour FunctionItem

Lors de la constitution des menus on aura

la_sonde = Sonde()
function_item = FunctionItem("calibrer la sonde", code_pour_calibrer, la_sonde)
menu.append_item(function_item)

Quand l’utilisateur choisira l’option “calibrer la sonde”, menucurses appellera la fct code_pour_calibrer avec comme argument la_sonde:

code_pour_calibrer(la_sonde)

dans code_pour_calibrer() on déterminera la relation de calibration a_rel et on terminera avant de retourner dans la Event Loop avec l’assignation suivante: la_sonde.set_calib_rel(a_rel)