Auteur: J.Vaucher
Version: 3.1
Date: 6 octobre 1997
Avec WindowTools, on peut dessiner des lignes, des ellipses et des rectangles avec diverses teintes de gris (ou de couleurs - a partir d'automne 97) et écrire du texte n'importe où sur une page. Il y a aussi des dialogues standards afficher des messages et pour demander des nombres et du texte. A peu près les mêmes possibilités qu'avec un BASIC ou Pascal pour ordinateur personnel. Avec un programme un peu plus compliqué, votre programme pourra attendre et réagir à divers événements; en particulier, vous pouvez specifier des procedures qui seront applées automatiquement suite à un Click de souris ou la sélection d'un Bouton.
En 1996-97, nos étudiants avaient accès à Windowtools avec une interface simplifiée appelée DESSIN; mais cet été (1997) nous avons intégré les bonnes idées de DESSIN directement dans WindowTools. Une conséquence de ceci est que Dessin n'est plus supporté mais il est relativement facile de convertir des vieux programmes [Voir section Conversion]. Nous avons aussi ajouté au package le traitement de la couleur et des images graphiques (.gif, .jpeg...etc...).
Le présent document présente un sous-ensemble des fonctions graphiques de WindowTools qui sont utiles pour IFT1010 et IFT1020. Pour plus de détails sur le package au complet, vous pouvez consulter:
Programme simple
Un programme simple qui ne fait qu'afficher des graphiques aura la structure suivante:
BEGIN external class windowtools; inspect new FirstWindow("ift1010") do begin <...votre code ..> endEND
Application Interactive
Une application graphique interactive qui doit réagir à divers événements comme des CLICKS ou l'entrée de chaque caractère aura une strucutre légèrement différente. En particulier, l'application doit être un OBJET distinct (spécialisation de MainWindow) créé avec NEW, par exemple:
BEGIN EXTERNAL class WINDOWTOOLS; MainWindow class exemple; begin ... votre code... ...avec procedure de captage d'evenements end; NEW exemple( "Titre..." ); END
% sim -simwin tp
% -------------------------------------------- % allo1.sim % ========= % Programme qui affiche Hello dans une fenetre % -------------------------------------------- begin external class windowtools; Inspect new FirstWindow("*** allo1 ***") do begin CenteredText(width/2, Height/2,"Hello World"); Sleep(4); end; end;Un programme plus complexe est donné plus loin.
Chaque programme WindowTools doit avoir exactement UNE fenêtre principale (soit un FIRSTWINDOW ou un MAINWINDOW). En plus, on pourra creer des fenêtres auxiliaires (SIDEWINDOW) en nombre quelconque. A l'intérieur de ces fenetre de premier niveau, vous pourrez ajouter d'autres éléments graphiques ou Widgets. Au niveau de X, ces widgets sont qui sont des fenêtre dépendantes, sous-classes de SUBWINDOW.
Une fenêtre FirstWindow reçoit automatiquement une fenêtre graphique de 600 x 400 pixels et les routines graphiques ci-dessous (comme ligne ou rectangle) dessinent dans cette fenêtre. Pour les MainWindow utilisˇes pour les applications avancˇes, il faut spˇcifier une taille avec SetSize (voir plus loin) et aussi les faire afficher explicitement (avec Show).
Il est aussi possible de créer plusieurs fenêtres avec MakeSideWindow(titre).
Les coordonnées sont exprimées en PIXELS. L'origine (le point <0,0>) est située au coin supérieur gauche des fenêtres; X augmente en allant vers la droite et Y augmente en allant vers le bas. Ceci est conforme aux conventions de X et du Mac.
Pour dessiner un rectangle de couleur avec un cadre, il faut faire deux appels, par exemple:
FillRectangle(50,10, 100, 50); DrawRectangle(50,10, 100, 50);
Les couleurs sont spécifiées sous forme de chaines de caratères (comme "red" ou "Orchid"). Celle-ci sont converties en format RGB par l'entremise d'un dictionnaire d'équivalences, "/usr/lib/X11/rgb.txt", fournies par le système X. Il est aussi possible d'utiliser des teintes de gris - allant de "gray0" (noir) a "gray100" (blanc) - ainsi que ^"black" et "white" Notez que le dictionnaire de couleur est basé sur l'anglais. Si vous entrez un nom de couleur en francais (p.e. vert) ou si vous faites une erreur d'orthographe (p.e. grean), une couleur aléatoire sera utilisée.
On peut aussi définir la couleur que l'on veut à l'aide de codes RGB. Le format de ces couleurs est simple: le premier caractère doit être le caractère '#', puis on code chaque couleur avec 1 ou 2 caractères hexadécimaux (de 0 à F). Ainsi, bleu serait #00F ou #0000FF.
Sur un terminal noir et blanc, les couleurs (et les gris) sont rendues par diverses combinaisons de points noir et blancs.
ref(button) mon_bouton ;Puis ils sont créés avec MakeButton en leur donnant un libellé:
mon_bouton :- MakeButton("Clear");Typiquement, on les clicks sur ces boutons seront captés par la procédure d'événement Button_press (voir plus loin); mais on peut aussi attendre avec:
mon_bouton.wait;Voici quelques operations permises sur les BOUTONs. Pour plus d'information, voir la documentation de WindowTools.
Les procedure suivantes demande une donnee a l'usager avec un PROMPT. Ces procedures font aussi la verification du type de ce qui est entre. Il y a une procedure pour chaque type de donnee: TEXT, INTEGER, CHAR, REAL et BOOL.
Dans ce cas, le message este affiche pour environs Delais secondes.
Les fonctions suivantes affiche des dialogues pour permettre a un usager de selectionner des noms de fichiers (ou de repertoires) de façon interactive.
procedure Handle_ButtonClick (B); ref(button) B;
procedure Handle_Click(X,Y); integer X,Y;
procedure WaitForClick(X,Y); integer X,Y;
Boolean procedure Clicked(X,Y); integer X,Y;
procedure handle_key_down(c);CHARACTER c;
procedure handle_left_arrow;
procedure handle_right_arrow;
procedure handle_up_arrow;
procedure handle_down_arrow;
procedure refresh;
Pour les débutants, ce genre de programme réactif semble étrange car le corps du programme ne fait rien: tout le travail est fait dans les procédures de traitement d'événements qui sont appelées "magiquement" en réaction à des actions graphiques.
Dans un programme qui fait de l'animation, il faut procéder autrement. Typiquement, le programme principal se trouve dans une boucle ou il déplace des icônes (en les effaçant et les redessinant ailleurs). Si votre programme ne fait jamais SLEEP et jamais WAIT, les événements ne sont pas traités. Dans ce cas, if faut explicitement permettre la vérification des événements en appelant une des dexu routines suivantes:
Handle_pending_events;Cette routine traite les evenements (s'il y en a) et ne fait rien sinon. La routine suivante attend et traite un evenement:
Handle_event;
Le programme ci-dessous (draw.sim ) montre l'emploi de boutons et de routines de captage d'événements. Remarquez les deux façon d'attendre que l'usager Clique sur le bouton STOP.
% >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % draw.sim : ce programme exploite la souris et les boutons pour % des dessins simples % >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BEGIN EXTERNAL class WINDOWTOOLS; MainWindow class exemple; begin integer X0, Y0; ref(button) Stop_b, Clear_b, Inverse_b; Boolean Finir; ! procedures pour capter Click et choix de boutons ; procedure Handle_Click(X,Y); integer X,Y; begin DrawLine( X0,Y0,X,Y); X0 := X; Y0 := Y; end; procedure Handle_ButtonClick(B); ref(button) B; if B == clear_b then Clear else if B == inverse_b then Flash else if B == Stop_b then finir := true; SetSize(600,400); Show; clear_b :- MakeButton("Clear"); inverse_b :- MakeButton("Invert"); Stop_b :- MakeButton("Stop"); X0 := width // 2; Y0 := height// 2; SetLineWidth(2); CenteredText(X0,50,"Clicker a divers endroits pour dessiner"); % pour attendre la FIN, % ---------------------------------------- while not finir do handle_event; % ou ---------------------------------- % stop_b.WAIT; % --------------------------------- end; new exemple("DRAW1.SIM"); END
Pour créer ces fenêtres, il faut utiliser la commande MakeSideWindow en spécifiant le nom (T) de la fenêtre.
ref(SideWindow) procedure MakeSideWindow(T); text T;Les fenêtres devront être désignées par des ref(dessin). Toutes les procédures graphiques décrites plus haut s'appliquent à ces fenêtes, mais il faut utiliser la notation pointée. Par exemple, pour créer un nouveau dessin dans lequel on affichera un cercle, on fera:
ref(SideWindow) D2;
D2 :- MakeSideWindow("Autre dessin");
D2.cercle( 100,100, 50, s_vide);
Pour montrer comment passer de DESSIN a WINDOWTOOLS, voici des exemples qui illustrent les différences. En gros, il faut remplacer DESSIN par WINDOWTOOLS et Application par MainWindow ou FirstWindow:
EXTERNAL class DESSIN; Application class exemple; begin ... votre code... ...avec procedure de captage d'evenements end;devient donc:
EXTERNAL class WINDOWTOOLS; MainWindow class exemple; begin ... votre code... ...avec procedure de captage d'evenements end;
begin external class dessin; Inspect new Application("*** allo1 ***") do begin Texte(width/2, Height/2,"Hello World"); Pause(4); end; end;
begin EXTERNAL CLASS WindowTools; Inspect new FirstWindow("*** allo1 ***") do begin CenteredText(width/2, Height/2,"Hello World"); Sleep(4); end; end;
% >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % draw.sim : ce programme exploite la souris et les boutons pour % des dessins simples % >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BEGIN EXTERNAL class DESSIN; Application class exemple; begin integer X0, Y0; ref(button) Stop_b, Clear_b, Inverse_b; Boolean Finir; ! procedures pour capter Click et choix de boutons ; procedure Mouse_click(X,Y); integer X,Y; begin ligne( X0,Y0,X,Y); X0 := X; Y0 := Y; end; procedure Button_press(B); ref(button) B; if B == clear_b then Effacer else if B == inverse_b then Flash else if B == Stop_b then finir := true; clear_b :- MakeButton("Clear"); inverse_b :- MakeButton("Invert"); Stop_b :- MakeButton("Stop"); X0 := width // 2; Y0 := height// 2; plume(2); texte(X0,50,"Clicker a divers endroits pour dessiner"); % pour attendre la FIN, % ---------------------------------------- while not finir do handle_event; % ou ---------------------------------- % stop_b.WAIT; % --------------------------------- end; new exemple("DRAW1.SIM"); END
V.