1. Composants lourds, composants légers
2. Architecture Modèle-Vue-Contrôleur
(MVC)
3.Système de conteneur pour afficher dans
une fenêtre ou une applet
1. Composants lourds, composants légers
En java, comme nous l'avons vu au chapitre AWT, les composants dérivent tous de la classe java.awt.Component. Les composants awt sont liés à la plate-forme locale d'exécution, car ils sont implémentés en code natif du système d'exploitation hôte et la Java Machine y fait appel lors de l'interprétation du programme Java. Ceci signifie que dès lors que vous développez une interface AWT sous windows, lorsque par exemple cette interface s'exécute sous MacOs, l'apparence visuelle et le positionnement des différents composants (boutons,...) changent. En effet la fonction système qui dessine un bouton sous Windows ne dessine pas le même bouton sous MacOs et des chevauchements de composants peuvent apparaître si vous les placez au pixel près (d'où le gestionnaire LayOutManager pour positionner les composants !).
De tels composants dépendant du système hôte sont
appelés en Java des composants lourds. En Java le composant lourd
est identique en tant qu'objet Java et il est associé localement lors
de l'exécution sur la plateforme hôte à un élément
local dépendant du système hôte dénommé
peer.
Tous les composants du package AWTsont des composants lourds. |
Par opposition aux composants lourds utilisant des peer de la
machine hôte, les composants légers sont entièrement
écrits en Java. En outre un tel composant léger n'est pas dessiné
visuellement par le système, mais en Java. Ceci apporte une amélioration
de portabilité et permet même de changer l'apparence de l'interface
sur la même machine grâce au "look and feel". La classe lookAndFeel
permet de déterminer le style d'aspect employé par l'interface
utilisateur.
Les composants Swing (nom du package : javax.swing) sont pour la majorité d'entre eux des composants légers. |
En Java on ne peut pas se passer de composants lourds (communiquant avec
le systme) car la Java Machine doit communiquer avec son système hôte.
Par exemple la fenêtre étant l'objet visuel de base dans les
systèmes modernes elle est donc essentiellement liée au système
d'exploitation et donc ce sera en Java un composant lourd. Dans le package
Swing le nombre de composants lourds est réduit au strict minimum
soient 4 genres de fenêtres.
1.3 Les fenêtres Swing sont des composants lourds
Les fenêtres en Java Swing :
Hiérarchie de classe de ces composants de fenêtres :
java.lang.Object +--java.awt.Component | +--java.awt.Container | +--java.awt.Window | | | +--javax.swing.JWindow | | | +--java.awt.Frame | | | | | +--javax.swing.JFrame | +--java.awt.Dialog | | | +--javax.swing.JDialog +--java.awt.Panel | +--java.applet.Applet | +--javax.swing.JApplet |
Le principe appliqué étant que si la fenêtre a besoin
de communiquer avec le système, les composants déposés
sur la fenêtre eux n'en ont pas la nécessité. C'est pourquoi
tous les autres composants de javax.swing sont des composants
légers. pour utiliser les Swing, il suffit d'importer le package :
Il est bien sûr possible d'utiliser des composants AWT et Swing dans
la même application. Les événements sont gérés
pour les deux packages par les méthodes de Listener du package
java.awt.event.
Ce qui signifie que tout ce qui a été dit au chapitre sur
les événements pour les composants AWT (modèle de délégation du traitement
de l'événement à un écouteur)
est intégralement reportable aux Swing sans aucune modification.
En général, les classes des composants swing étendent les fonctionnalités des classes des composants AWT dont elles héritent (plus de propriétés, plus d'événements,...). |
1.4 Les autres composants Swing sont légers
Les composants légers héritent tous directement ou indirectement
de la classe javax.swing.JComponent :
java.lang.Object | +--java.awt.Component | +--java.awt.Container | +--javax.swing.JComponent |
Dans un programme Java chaque composant graphique Swing (léger) doit donc disposer d'un conteneur de plus haut niveau sur lequel il doit être placé.
Afin d'assurer la communication entre les composants placés dans une fenêtre et le système, le package Swing organise d'une manière un peu complexe les relations entre la feêtre propriétaires et ses composants.
Exemple la classe JFrame de fenêtre classique avec barre de titre,
bordure et possibilité de barre de menus.
Le JDK1.4.2 donne la liste suivante des composants légers héritant
de JComponent :
AbstractButton, BasicInternalFrameTitlePane, JColorChooser,
JComboBox, JFileChooser, JInternalFrame, JInternalFrame.JDesktopIcon, JLabel,
JLayeredPane, JList, JMenuBar, JOptionPane, JPanel, JPopupMenu, JProgressBar,
JRootPane, JScrollBar, JScrollPane, JSeparator, JSlider, JSplitPane, JTabbedPane,
JTable, JTableHeader, JTextComponent, JToolBar, JToolTip, JTree, JViewport.
2. Architecture Modèle-Vue-Contrôleur
2.1 L'architecture Modèle-Vue-Contrôleur en général
En technologie de conception orientée objet il est conseillé de ne pas confier trop d'actions à un seul objet, mais plutôt de répartir les différentes responsabilités d'actions entre plusieurs objets. Par exemple pour un composant visuel (bouton, liste etc...) vous déléguez la gestion du style du composant à une classe (ce qui permettra de changer facilement le style du composant sans intervenir sur le composant lui-même), vous stockez les données contenues dans le composant dans une autre classe chargée de la gestion des données de contenu ( ce qui permet d'avoir une gestion décentralisée des données) .
Si l'on recense les caractéristiques communes aux composants visuels
servant aux IHM (interfaces utilisateurs), on retrouve 3 constantes générales
pour un composant :
Diagramme de séquence UML des interactions
MVC
2.2 Le pluggable look and feel
C'est grâce à cette architecture que l'on peut implémenter la notion de "pluggable look and feel (ou plaf)" qui entend séparer le modèle sous-jacent de la représentation visuelle de l'interface utilisateur. Le code Swing peut donc être réutilisé avec le même modèle mais changer de style d'interface dynamiquement pendant l'exécution.
Voici à titre d'exemple la même interface Java écrite avec des Swing et trois aspects différents (motif, métal, windows) obtenus pendant l'exécution en changeant son look and feel par utilisation de la classe UIManager servant à gérer le look and feel.
avec le système Windows sont livrés 3 look and feel standard
: windows (apparence habituelle de windows), motif (apparence graphique Unix)
et metal (apparence genre métallique).
2.3 Trois exemples de look and feel
Voici ci-après trois aspects de la même interface utilisateur,
chaque aspect est changé durant l'exécution uniquement par
l'appel des lignes de code associées (this représente la fenêtre
JFrame de l'IHM) :
Lignes de code pour passer en IHM motif :
String UnLook = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"
;
try {
UIManager.setLookAndFeel(UnLook); // assigne le look and feel choisi ici motif
SwingUtilities.updateComponentTreeUI(this.getContentPane(
)); // réactualise le graphisme de
l'IHM
}
catch (Exception exc) {
exc.printStackTrace( );
}
Aspect motif de l'IHM
String UnLook = "javax.swing.plaf.metal.MetalLookAndFeel" ;
try {
UIManager.setLookAndFeel(UnLook); // assigne le look and feel choisi ici metal
SwingUtilities.updateComponentTreeUI(this.getContentPane(
)); // réactualise le graphisme de
l'IHM
}
catch (Exception exc) {
exc.printStackTrace( );
}
Aspect métal de l'IHM
String UnLook = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"
;
try {
UIManager.setLookAndFeel(UnLook); // assigne le look and feel choisi ici windows
SwingUtilities.updateComponentTreeUI(this.getContentPane(
)); // réactualise le graphisme de
l'IHM
}
catch (Exception exc) {
exc.printStackTrace( );
}
Aspect Windows de l'IHM
2.4 Les swing reposent sur MVC
Les composants de la bibliothèque Swing adoptent tous cette
architecture de type MVC (Modèle-Vue-Contrôleur)
qui sépare le stockage des données, leur représentation
et les interactions possibles avec les données, les composants sont
associés à différentes interfaces de modèles
de base. Toutefois les swing pour des raisons de souplesse ne respectent
pas strictement l'architecture MVC que nous venons de citer :
Exemple de quelques interfaces de modèles rencontrées
dans la bibliothèque Swing
Identificateur de la classe de modèle | Utilisation |
ListModel | Modèle pour les listes (JList ...) |
ButtonModel | Modèle d'état pour les boutons (JButton...) |
Document | Modèle de document (JTextField... |
La mise en oeuvre des composants Swing ne requiert pas systématiquement l'utilisation des modèles. Il est ainsi généralement possible d'initialiser un composant Swing à l'aide des données qu'il doit représenter. Dans ce cas , le composant exploite un modèle interne pour stocker les données.
Le composant javax.swing.Jlist
Dans le cas du JList le recours au modèle est impératif, en particulier une vue utilisant le modèle ListModel pour un jList enregistrera un écouteur sur l'implémentation du modèle et effectuera des appels à getSize( ) et getElementAt( ) pour obtenir le nombre d'éléments à représenter et les valeurs de ces éléments.
Dans l'exemple suivant, l'un des constructeurs de JList est employé afin de définir l'ensemble des données à afficher dans la liste, on suppose qu'il est associé à un modèle dérivant de ListModel déjà défini auparavant. L'appel à getModel( ) permet d'obtenir une référence sur l'interface ListModel du modèle interne du composant :
JList Jlist1 = new JList(new Objet[] {"un","deux","trois"});Pour mettre en oeuvre les modèles et les fournir aux composants on utilise la méthode setModel( ) (public void setModel (ListModel model) { } ) du composant. Comme ListModel est une interface, il nous faut donc implémenter cette interface afin de passer un paramètre effectif (ListModel model ), nous choisissons la classe DefaultListModel qui est une implémentation de l'interface ListModel par le biais d'un vecteur. Il est ainsi possible d'instancier le ListModel d'agir sur le modèle (ajout, suppression d'éléments) et de l'enregistrer auprès du composant adéquat grâce à setModel( ).
ListModel modeldeliste = jList1.getModel( );
System.out.println ("Élément 0 : " + modeldeliste.getElementAt(0));
System.out.println ("Nb éléments : "+ modeldeliste.getSize( ))
Le listing suivant illustre la mise en oeuvre de DefaultListModel(
) pour un JList :
JList jList1 = new JList( ); DefaultListModel dlm = new DefaultListModel ( ); |
// instanciations d'un JList et d'un modèle. |
dlm.addElement ("un"); dlm.addElement ("deux"); dlm.addElement ("trois"); dlm.addElement ("quatre"); |
// actions d'ajout d'éléments dans le modèle. |
jList1.setModel(dlm); | // enregistrement du modèle pour le JList. |
dlm.removeElementAt(1); dlm.removeRange(0,2); dlm.add(0,"Toto"); |
// actions de suppression et d'ajout d'éléments dans le modèle. |
Une IHM dans laquelle, le bouton Ajouter, insère
7 chaînes dans chacun des deux composants.
L'apparence est la même lors de l'affichage des données
dans chacun des composants, dans le code il y a une totale différence
de gestion entre le composant List et le composant Jlist.
Comme en Delphi le composant java.awt.List gère lui-même le stockage des données, et la barre de défilement verticale.
List list1 = new List();
list1.add("un");
list1.add("deux");
list1.add("trois");
list1.add("quatre");
list1.add("cinq");
list1.add("six");
list1.add("sept");
Le composant javax.swing.Jlist délègue le stockage des données à un modèle et la gestion de la barre de défilement verticale à un autre composant dédié : un javax.swing.JscrollPane.
JList jList1 = new JList();
DefaultListModel dlm = new DefaultListModel();
JScrollPane jScrollPane1 = new JScrollPane();
jList1.setModel(dlm);
jScrollPane1.getViewport().add(jList1);
dlm.addElement("un");
dlm.addElement("deux");
dlm.addElement("trois");
dlm.addElement("quatre");
dlm.addElement("cinq");
dlm.addElement("six");
dlm.addElement("sept");
3.Système de conteneur pour afficher dans une fenêtre ou une applet
En Java le JFrame est un conteneur de composants (barre de menus, boutons etc...) qui dispose de 4 niveaux de superposition d'objets à qui est déléguée la gestion du contenu du JFrame.
Notons que le JRootPane, le JLayredPane et le GlassPane sont utilisés par Swing pour implémenter le look and feel, ils n'ont donc pas à être considérés dans un premier temps par le développeur, la couche qui nous intéresse afin de déposer un composant sur une fenêtre JFrame est la couche ContentPane instanciation de la classe Container. Les rectangles colorés imbriqués ci-haut, sont dessinés uniquement à titre pédagogique afin d'illustrer l'architecture en couche, ils ne représentent pas des objets visuels dont les tailles seraient imbriquées. En effet le GlassPane bien que dessiné plus petit (pour mieux le situer) prend par exemple toute la taille du Contentpane.
Swing instancie automatiquement tous ces éléments dès que vous instanciez un JFrame (à part JMenuBar qui est facultatif et qu'il faut instancier manuellement).
Pour ajouter des composants à un JFrame, il faut les ajouter à
son objet ContentPane (la référence de l'objet est obtenu par
la méthode getContentPane( ) du JFrame).
3.1 Exemple d'ajout d'un bouton à une fenêtre
Soit à ajouter un bouton de la classe des JButton sur une fenêtre de la classe des JFrame :
JFrame LaFenetre = new JFrame( ) ; // instanciation d'un JFrame
JButton UnBouton = new JButton( ) ; // instanciation d'un JButton
Container ContentPane = LaFenetre.getContentPane(
) ; // obtention de la référence du
contentPane du JFrame
....
ContentPane.setLayout(new XYLayout( )); // on choisi le layout manager du ContentPane
ContentPane.add(UnBouton) ; // on dépose
le JButton sur le JFrame à travers son ContentPane
....
Attention : avec AWT le dépôt du composant s'effectue
directement sur le conteneur. Il faut en outre éviter de mélanger
des AWT et des Swing sur le même conteneur.
AWT | Swing |
Frame LaFenetre = new Frame( ) ; Button UnBouton = new Button( ) ; LaFenetre.add(UnBouton) ; |
JFrame LaFenetre = new JFrame( ) ;
JButton UnBouton = new JButton( ) ; Container ContentPane = LaFenetre.getContentPane( ) ; ContentPane.add(UnBouton) ; |
L'IDE Java JGrasp de l'université d'Auburn (téléchargement en freeware à Auburn) permet le développement d'applications pédagogiques dès que vous avez installé la dernière version du JDK (téléchargement en freeware chez Sun). Si vous voulez bénéficier de la puissance équivalente à Delphi pour écrire des applications fenêtrées il est conseillé d'utiliser un RAD (sauf à aimer les réexécutions fastidieuses pour visualiser l'état de votre interface).
JBuilder est un outil RAD particulièrement puissant et convivial aide au développement d'application Java avec des IHM (comme Delphi le fait avec pascal). La société Borland qui s'est spécialisé dans la création de plate-formes de développement est leader avec ce RAD sur le marché des IDE (une version personnelle est en téléchargement freeware chez Borland).
Nous recommandons donc au débutant en Java d'adopter ces deux
outils dans cet ordre , une fois aguerri, JBuilder deviendra l'environnement
de base.