Interfaces graphiques (GUIs) Cours 2a : Programmation des interfaces graphiques jgarcia@ircam.fr l'interaction graphique : les entrées sont spécifiées directement à partir des sorties. Le périphérique d entrée spécifie une commande de position à l'écran qui désigne un objet précédemment affiché par le système (pointage). Elle est familière dans le monde physique. (partie de la présentation basée sur des transparents d Anastasia Bezerianos, Fanis Tsandilas et Michel Beaudouin-Lafon) Interfaces WIMP Couches logicielles WIMP : Window, Icons, Menus and Pointing Fenêtres, Icones, menus et pointage. Présentation Fenêtre, icones et autres objets graphiques Interaction Menus, boites de dialogue, texte Entrée pointage, sélection, tracé Boucle action perception Feedback Squelette d application MacApp Java Swing, Qt, GTK+, MFC, Cocoa X Windows GDI+, Quartz, GTK+/Xlib, OpenGL Windows, Mac OS X, Linux
Couches logicielles Dispositifs d entrée/sortie Squelette d application MacApp Entrée : Saisir des commandes et des données Sortie : le système affiche de l information et montre son état Java Swing, Qt, GTK+, MFC, Cocoa X Windows GDI+, Quartz, GTK+/Xlib, OpenGL Windows, Mac OS X, Linux Interactivité vs. Algorithmique système algorithmique (fermés) : lit des entrées, calcule, produit un résultat il y a un état final système interactif (ouverts) : évènements provenant de l extérieur boucle infinie, non déterministe Problème vous avez appris à programmer des algorithmes (la partie calcul ) la plupart des langages de programmation (C, C ++, Java, Lisp, Scheme, Ada, Pascal, Fortran, Cobol,...) sont conçus pour écrire des algorithmes, pas des systèmes interactifs
Problème Traitement des entrées/sorties pendant le calcul Instructions de sortie (print, put, send, ) pour envoyer des données aux périphériques Instructions de lecture (read, get, receive, ) pour lire l état ou changement d états de périphériques d entrée, du façon bloquante Problème obligés d écrire des SI sous une forme algorithmique : afficher deux boutons B1 et B2 fini <- faux tantque non fini faire bouton <- attendreclic () // attente bloquante selon bouton B1 : afficher «Bonjour» B2 : fini <- vrai fin fin Comment gérer les entrées Programmation évènementielle - - 1 pér. à la fois - Attente active - état des plusieurs pér. - CPU File d attente (queue) while active if queue is not empty event <- queue.dequeue() source <- findsource(event) source.processevent(event) end if end while queue.enqueue(event)
Programmation évènementielle Exemple : Swing (AWT) Source : Mouse Click File d attente (queue) queue.enqueue(event) Cible : Bouton «Cancel» while active if queue is not empty event <- queue.dequeue() source <- findsource(event) source.processevent(event) end if end while processevent(event) target <- FindTarget (event) if (target NULL) target.processevent(event) 3 processus Initial : main() EDT gères la liste d évènements : envoie les évènements aux listeners et appel la méthode paint Tache de fond : exécute les actions plus longues Couches logicielles Constructeurs d interface Squelette d application MacApp Java Swing, Qt, GTK+, MFC, Cocoa X Windows GDI+, Quartz, GTK+/Xlib, OpenGL Windows, Mac OS X, Linux Exemples : MS Visual Studio (C++, C#, etc.), NetBeans (Java), Interface Builder (ObjectiveC)
Constructeurs d interface Utiles pour : Créer des prototypes Tests d apparence Conception rapide Débutants Boîte à outils d interface Bibliothèques d objets interactifs (les «widgets») que l on assemble pour construire l interface Fonctionnalités pour faciliter la programmation d applications graphiques interactives Attention à la qualité du code généré Boîte à outils d interface Pourquoi Java Swing Java (toutes plateformes et beaucoup de librairies) Beaucoup de ressources en ligne
Pourquoi Java Swing Java (toutes plateformes et beaucoup de librairies) Beaucoup de ressources en ligne bouton les «widgets» menu fenêtre barre d outils Alternatives JavaFX : s impose petit à petit pour les interfaces en Java car permet de travailler avec beaucoup de matériel différent. zone de texte onglet étiquette bouton radio liste barre de défilement «slider» les widgets de Swing les widgets de Swing
Complexité des widgets Hiérarchie des widgets un composant ne peut appartenir qu à un seul «container» widgets «simples» buttons, barres de défilement, widgets «composés» Destinés à contenir d autres widgets (simples ou composés) Boites de dialogue, menus, Racine (composé) correspond à une fenêtre de l appli Nœuds (composé) Structure visuel ou fonctionnel du contenu Feuille (simple) avec lesquels l utilisateur peut interagir Classes des widgets SWING JFrame Une application graphique à un containeur principal qui contient tous les autres. 3 types différents dans SWING : Jframe, Jdialog et Japplet Public static void main (String[] args) { JFrame frame = new JFrame (Ma première fenêtre); frame.setvisible(true); } Ils contiennent tous des widgets qui sont contenus dans le content pane
Dialog Exercice Public static void main (String[] args) { JFrame frame = new JFrame («Ma première fenêtre»); frame.setvisible(true); JDialog dialog = new JDialog (frame, «Hello world», true); Identifier les widgets de cette interface } Modale les «widgets» bouton menu fenêtre barre d outils Facettes des widgets onglet étiquette zone de texte bouton radio liste barre de défilement «slider»
Facettes des widgets Facettes des widgets Présentation apparence graphique Comportement réactions aux actions de l utilisateur Interfaçage avec l application : notifications de changement d état Exemple : Bouton Présentation cadre avec un nom à l intérieur Comportement «enfoncement» ou «relâchement» lorsque l on clique dessus Interfaçage avec l application : fonction appelée lorsque le bouton est cliqué Facettes des widgets Facettes d un widget Exemple : Slider Présentation? Comportement? Notifications de changement d état : variables actives (Tcl/Tk) envoi d évènements(qt) fonctions de rappel («callbacks») Interfaçage avec l application :?
Variables actives Envoi d évènements lien bidirectionnel entre une variable d état du widget et une variable de l application Les widgets agissent comme des périphériques d entrée et envoient des évènements. Une boucle tant que lit et traite les évènements Association d un objet à un widget et de méthodes de l objet aux changements d état problèmes limité aux types simples lien de retour peut être coûteux Erreurs si les liens sont mis à jour par des développeurs Envoi d évènements Sépare l envoi et le traitement des évènements Fonctions de rappel Enregistrement lors de la création du widget Meilleure encapsulation Appel lors l activation du widget
Fonctions de rappel Problème : spaghetti des callbacks Partage d état entre plusieurs callbacks par : variables globales Trop dans une application réelle arbre des widgets : la fonction de rappel est appelée en lui passant le widget qui l a déclenché Fragile si l on change la structure, insuffisante pour d autres données pas associés aux widgets «jeton» (token) : donnée enregistrée avec la callback, passée automatiquement au moment de l appel fonctions de rappel /* fonction de rappel */ void DoSave (Widget w, void* data) { /* récupérer le nom de fichier */ filename = (char**) data; /* appeler la fonction de l application */ SaveTo (filename); /* fermer la boîte de dialogue */ CloseWinfow (getparent(getparent(w))); } /* programme principal */ main () { /* variable contenant le nom du fichier */ char* filename = ; /* créer le widgets et lui associer sa callback */ ok = CreateButton (...); RegisterCallback (ok, DoSave, (void*) &filename); /* boucle de traitement des événements */ MainLoop (); } «event listeners» (Java) «event listeners» (Java) Variante des callbacks adaptée au Java: Méthodes de type AddListener spécifient non pas une fonction de callback, mais un objet (le listener) Lorsque le widget change d état, il déclenche une méthode prédéfinie du listener (par exemple actionperformed) public class ClickListener implements ActionListener { public void actionperformed(actionevent e){ JButton button = (JButton)e.getSource(); } } ClickListener listener = new ClickListener(); JButton button = new JButton( Click me ); button.addactionlistener(listener);
«event listeners» (Java) Anonymous Inner classes button.addactionlistener(new ActionListener(){ public void actionperformed(actionevent e){ } }); panel.addmouselistener(new MouseAdapter(){ public void mouseclicked(mouseevent e){ } }); Fonctions et évènements prédéfinis «event listeners» (Java) Anonymous Inner classes new <nom-de-classe> () { <corps> } cette construction fait deux choses : elle crée une nouvelle classe, sans nom, qui est une sous-classe de <nom-de-classe> définie par <corps> elle crée une instance (unique) de cette nouvelle classe et retourne sa valeur Cette class a accès aux variables et méthodes de la classe dans la quelle elle est définie Evènements et Ecouteurs Evènements et Ecouteurs Chaque évènement à une source (Jbutton, JRadioButton, Jmenu, JTextField) à laquelle on accède via la méthode getsource() Les listeners doivent implémenter l interface qui correspond aux évènements. Ex : ActionEvent => ActionListener Tous les évènements héritent de la classe EventObject Tous les listeners héritent de EventListener Quelques couple Events Listener ActionEvent ActionListener MouseEvent MouseListener KeyEvent KeyListener
Evènements et Ecouteurs Exercice Les listeners doivent être enregistrés (ajoutés) aux widgets. Un listener peut être ajouté à plusieurs widgets. Un listener pour plusieurs boutons par exemple Identifier les listeners de cette interface Un widget peut avoir plusieurs listeners Un pour le click et un pour la touche entrée sur un bouton «drag-and-drop» Quels sont les «widgets» affectés? Quels sont les évènements? «drag-and-drop» Quels sont les «widgets» affectés? Quels sont les évènements? Exercice : comment décrire cette interaction avec un «event listener»? Exercice : comment décrire cette interaction avec un «event listener»? http://openclassrooms.com/courses/apprenez-a-programmer-en-java/le-drag-n-drop