Interfaces graphiques (GUIs) Cours 2a : Programmation des interfaces graphiques [email protected] 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 Entrée : Saisir des commandes et des données Sortie : le système affiche de l’information et montre son état Squelette d’application MacApp 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 - 1 pér. à la fois - Attente active - état des plusieurs pér. - CPU Programmation évènementielle File d’attente (queue) queue.enqueue(event) while active! if queue is not empty! event <- queue.dequeue()! source <- findSource(event)! source.processEvent(event)! end if! end while! ! ! ! ! Programmation évènementielle 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)! ! ! ! ! Couches logicielles Squelette d’application Exemple : Swing (AWT) 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 Constructeurs d’interface 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 les « widgets » bouton menu fenêtre barre d’outils onglet Alternatives • JavaFX : s’impose petit à petit pour les interfaces en Java car permet de travailler avec beaucoup de matériel différent. étiquette zone de texte 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 » Racine (composé) correspond à une fenêtre de l’appli buttons, barres de défilement, … widgets « composés » Nœuds (composé) Structure visuel ou fonctionnel du contenu Destinés à contenir d’autres widgets (simples ou composés) Boites de dialogue, menus, … Feuille (simple) avec lesquels l’utilisateur peut interagir Classes des widgets SWING Une application graphique à un containeur principal qui contient tous les autres. 3 types différents dans SWING : Jframe, Jdialog et Japplet Ils contiennent tous des widgets qui sont contenus dans le content pane JFrame Public static void main (String[] args) { JFrame frame = new JFrame (Ma première fenêtre); frame.setVisible(true); } 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 Facettes des widgets fenêtre barre d’outils onglet étiquette zone de texte bouton radio liste barre de défilement « slider » Facettes des widgets Présentation Facettes des widgets Exemple : Bouton apparence graphique Présentation Comportement cadre avec un nom à l’intérieur réactions aux actions de l’utilisateur Comportement Interfaçage avec l’application : notifications de changement d’état « 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 Exemple : Slider Présentation ? Comportement ? Interfaçage avec l’application : ? Facettes d’un widget Notifications de changement d’état : – variables actives (Tcl/Tk) – envoi d’évènements(Qt) – fonctions de rappel (« callbacks ») 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 « event listeners » (Java) Variante des callbacks adaptée au Java: 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) public class ClickListener implements ActionListener {! !public void actionPerformed(ActionEvent e){! Méthodes de type AddListener spécifient non pas une fonction de callback, mais un objet (le listener) ! !JButton button = (JButton)e.getSource();! ! !…! !}! }! ! Lorsque le widget change d’état, il déclenche une méthode prédéfinie du listener (par exemple actionPerformed) …! 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 ! Evènements et Ecouteurs Chaque évènement à une source (Jbutton, JRadioButton, Jmenu, JTextField) à laquelle on accède via la méthode getSource() « 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 Tous les évènements héritent de la classe EventObject Tous les listeners héritent de EventListener Les listeners doivent implémenter l’interface qui correspond aux évènements. Ex : ActionEvent => ActionListener Quelques couple Events – Listener • ActionEvent ActionListener • MouseEvent MouseListener • KeyEvent KeyListener • … Evènements et Ecouteurs Les listeners doivent être enregistrés (ajoutés) aux widgets. Exercice Identifier les listeners de cette interface Un listener peut être ajouté à plusieurs widgets. Un listener pour plusieurs boutons par exemple Un widget peut avoir plusieurs listeners Un pour le click et un pour la touche entrée sur un bouton « drag-and-drop » « drag-and-drop » Quels sont les « widgets » affectés ? Quels sont les évènements? 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