
|
auteur :
Johann Heymes | Tout d'abord, il faut rappeler que la librairie AWT a été développée pour la première sortie de Java version 1.0 du jdk alors que Swing n'est apparue qu'à la version 1.2 du jdk (soit Java 2). Il en résulte donc des différences fondamentales de conception entre les deux librairies.
Composant AWT : Un composant AWT lors de sa création est associé à une fenêtre distincte (un homologue, peer en anglais) gérée par le système d'exploitation sous-jacent. Et c'est cet homologue qui est responsable de son apparence. Cette "manière" de faire, bien qu'elle ait fait ses preuves et qu'elle ait permis au langage Java de s'imposer, est très lourde (perte de performance, et consommation excessive de mémoire). C'est pour cette raison que l'on qualifie les composants AWT par heavyweight (littéralement, poids lourds)
Composant Swing : Par opposition, les composants Swing sont simplement dessinés à l'intérieur de leur conteneur comme s'il s'agissait d'une image, et aucun homologue du système sous jacent ne leur est affecté. C'est pourquoi ils sont qualifiés de lightweight (composants allégés).
Nous noterons également que lors du développement avec AWT il suffit d'ajouter les composants directement au Top-level Container (Conteneur de Haut Niveau) tel que Frame, Applet, ..., alors que sous Swing il est nécéssaire de les ajouter à un volet de contenu (Cf : javax.swing.JRootPane). De manière plus parlante je veux parler du :
jframe.getContentPane().add(monComposant);
Voila, ces quelques différences ne sont bien sûr pas exhaustives, Swing posséde bien d'autres avantages, je ne citerai que : la gestion de bordure, les info-bulles, le défilement, les Look And Feel, de nouveaux LayoutManager, ainsi que l'architecture MVC (Model-View-Control). Maintenant que l'on a conscience de ces différences, une question reste tout de meme en suspens... Peut-on mélanger Awt et Swing ?
|
|
auteur :
Johann Heymes | NON Il est impossible d'obtenir un rendu graphique correct dans une application qui mélange AWT et SWING. Des problèmes de superposition empêchent toute collaboration.
Le composant JFrame comprend un objet fils qui prend en charge tout ce qui concerne le graphique, il s'agit d'une instance de JRootPane. Le composant JRootPane est lui même structuré. Il contient un volet structuré en couche (instance de JLayeredPane) et un volet structuré en pellicule (GlassPane).
- Le composant LayeredPane permet d'insérer une barre de menu ainsi que tout autre composant (cela fait référence au fameux contentPane de jframe.getContentPane ()). il est également chargé du Z-ordering (algorithme permettant de ne dessiner que les parties non cachées, suite aux superpositions de composant).
- Le composant GlassPane représente une pellicule qui recouvre tout et qui par exemple peut intercepter tous les événements souris de l'interface graphique.
import javax.swing.*;
import java.awt.*;
public class AWTSwing {
private JComboBox combo;
private Button bouton;
public AWTSwing () {
JFrame frame = new JFrame ("Peut-on melanger Awt & Swing ?");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setBounds (300, 300, 200, 300);
String [] a = {"oui", "non", "peut etre"};
combo = new JComboBox (a);
frame.getContentPane ().add (combo, BorderLayout.NORTH);
bouton = new Button ("Coucou");
frame.getContentPane ().add (bouton, BorderLayout.CENTER);
frame.setVisible (true);
}
public static void main (String argv []) {
new AWTSwing ();
}
}
Lorsque l'on ouvre le menu contextuel du JComboBox, ce dernier est caché par le composant bouton de type java.awt.Button. - Le rendu graphique du composant "bouton" issu de la librairie AWT est délégué à son homologue (peer), par conséquent la position Z est la même que celle de la Frame (soit de haut niveau)
- Alors que le composant "combo" de type JComcoBox (Swing) n'est que "dessiné" comme une image sur le conteneur (soit de bas niveau)
La seule solution envisageable est d'uniformiser le code sur la librairie graphique utilisée, soit tout AWT, soit tout Swing !
|
téléchargement : AWTSwing.java
|
|
auteur :
Johann Heymes | On peut utiliser la classe java.lang.Thread ou implémenter l'interface java.lang.Runnable, mais suivant les cas de figure cela représente beaucoup de code et de contraintes. En effet, les instructions qui affectent ou dépendent d'un composant graphique Swing doivent être effectuées par le processus d'évènement (the event-dispatching thread). Par conséquent si l'on utilise la classe Thread ou l'interface Runnable il est nécessaire d'utiliser les méthodes : invokeLater(java.lang.Runnable) ou invokeAndWait(java.lang.Runnable)" javax.swing.SwingUtilities.
La classe Timer : La classe javax.swing.Timer remplace avantageusement l'utilisation directe de thread. Elle génère un évènement à intervalles réguliers (à la milli-seconde). C'est le "event-dispatching thread" qui exécute l'évènement, donc on peut directement modifier des objets graphiques.
Méthodes importantes : le constructeur de javax.swing.Timer :
public Timer (int delay, ActionListener listener);
/** delay = l'intervalle de temps entre chaque évènement.
* listener = l'objetécouteur de ces evènements.
*/
méthode permettant de lancer le processus :
public void start();
méthode permettant de stopper le processus :
public void stop();
Note : Cette méthode est à utiliser uniquement si le traitement à faire est court en temps d'exécution sinon on aura une interface non réactive pendant le traitement ....
|
téléchargement : Exemple d'utilisation pour faire un compteur.
|
|
auteur :
Clément Cunin | JDK 1.3 et inférieur : Lorsque l'on utilise la méthode show(java.awt.Component, int, int) pour afficher un javax.swing.JPopupMenu, les coordonnées correspondent au coin haut-gauche du menu. Si ces coordonnées sont trop près du bord de l'écran, une partie du menu est alors cachée. Nous allons donc surcharger la méthode show() pour que les coordonnées soient corrigées si le message est trop proche du bord de l'écran.
class MonPopupMenu extends JPopupMenu {
public void show(Component invoker, int x, int y) {
/**Dimension de l'écran */
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
/** Dimension du Menu popup */
Dimension popupSize = this.getPreferredSize();
/** Position en x,y du popup à l'écran (pour le .show) */
double xPopupEcran = invoker.getLocationOnScreen().getX() + x;
double yPopupEcran = invoker.getLocationOnScreen().getY() + y;
/** Si le popup déborde de l'écran sur la droite on décale sur x */
if ((xPopupEcran + popupSize.getWidth()) > screenSize.getWidth()) {
x = x - (int)popupSize.getWidth();
}
/** Si le popup déborde de l'écran sur le bas on décale sur y */
if ((yPopupEcran + popupSize.getHeight()) > screenSize.getHeight()) {
y = y - (int)popupSize.getHeight();
}
/** On affiche le popup à l'endroit judicieusement calculé :) */
super.show(invoker, x, y);
}
}
JDK 1.4 : Ce bug a été résolu dans la version 1.4 de l'API. Le correctif n'est pas nécessaire.
|
|
auteur :
L'équipe Java | Ce n'est pas directement possible en AWT, il faut créer sa propre classe MyButton permettant de le faire en dérivant par exemple Component pour faire un lightweigth component.
|
|
auteur :
bulbo | La classe AbstractButton définit un ensemble de méthodes permettant d'indiquer comment doit se dessiner le bouton. Ainsi, on peut indiquer, par exemple, si on désire dessiner les rebords ou le contenu. Voici un exemple.
Le code ci-dessous dessine un bouton transparent, seul le texte sera affiché en rouge.
JButton printButton = new JButton("Imprimer");
printButton.setForeground(Color.red);
printButton.setFocusPainted(false);
printButton.setBorderPainted(false);
printButton.setContentAreaFilled(false);
|
|
auteur :
L'équipe Java | Voilà un début de code permettant d'imprimer un Container 'cont'.
/** Récupère le travail et affiche la boite de dialogue d'impression */
PrintJob job = getToolkit().getPrintJob(frame_parent_pour_le_dialogue,"essai", null);
if (job != null) {
/** Recupere le Graphics dans lequel on va ecrire */
Graphics g = job.getGraphics();
if (g != null) {
/** Sur le Container imprime l'ensemble de ses Components */
cont.printAll(g);
g.dispose();
}
/** Finit le travail */
job.end();
}
|
|
auteur :
Clément Cunin | Quand et pourquoi ? Ce problème est très classique lors d'un long traitement dans une application graphique. En Java, un processus est chargé de toutes les opérations liées à l'affichage et à la gestion des évènements, le processus "the event dispatching thread". Si une application utilise ce processus pour faire un traitement de plusieurs minutes, c'est autant de temps où l'application ne sera plus réactive aux actions de l'utilisateur, ni aux mise à jour graphiques (d'une barre de progression par exemple).
Solution : La solution est assez simple à comprendre : tout traitement long doit être effectué par un autre processus.
|
lien : Qu'est ce qu'un thread ?
|
|
auteur :
Ioan Calapodescu | Pour faire cela, il faut utiliser la classe UIManager. Par exemple :
try {
UIManager.setLookAndFeel("mon.look.and.Feel");
} catch (InstantiationException e) {
} catch (ClassNotFoundException e) {
} catch (UnsupportedLookAndFeelException e) {
} catch (IllegalAccessException e) {}
Si vous changez le look and feel de votre application en cours d'exécution, vous devez la rafraîchir en utilisant SwingUtilities.updateComponentTreeUI. Voici un exemple changeant le look and feel de l'application pour le look and feel natif (celui naturellement utilisé par le système).
JFrame frame = new JFrame();
frame.setVisible(true);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(frame);
} catch (InstantiationException e) {
} catch (ClassNotFoundException e) {
} catch (UnsupportedLookAndFeelException e) {
} catch (IllegalAccessException e) {}
|
lien : Comment lister les Look & Feel disponibles ?
|
|
auteur :
Ioan Calapodescu | Les look and feels enregistrés sont disponibles avec la méthode getInstalledLookAndFeels de la classe UIManager. Voici un exemple récupérant l'ensemble des look and feels sous forme de Map, dont les clefs sont les noms des L&F et les valeurs les noms des classes correspondantes.
public Map getLookAndFeelsMap(){
UIManager.LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels();
Map map = new TreeMap();
for(int i=0; i<info.length;i++){
String nomLF = info[i].getName();
String nomClasse = info[i].getClassName();
map.put(nomLF,nomClasse);
}
return map;
}
Pour un exemple utilisant cette méthode regardez le fichier ci-dessous.
|
lien : Comment changer le Look & Feel de mon aplication ?
téléchargement : Menu Look and Feel
|
|
auteur :
laffreuxthomas | Vous souhaitez associer des boutons de votre interface graphique aux touches ENTER et ESCAPE, et ceci quel que soit le composant qui ai le focus lors de l'appui sur ces touches ?
Pour la touche ENTER c'est très simple parce que c'est fait pour :
maFrame.getRootPane().setDefaultButton(monBouton)
monDialog.getRootPane().setDefaultButton(monBouton)
Pour la touche ESCAPE c'est plus compliqué, une solution est d'associer du code à l'évènement (et non pas un bouton) :
private void configureRootPane(JRootPane rootPane) {
InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escPressed");
rootPane.getActionMap().put(
"escPressed",
new AbstractAction("escPressed") {
public void actionPerformed(ActionEvent actionEvent) {
onKeyEscape();
}
});
}
...
configureRootPane(maFrame.getRootPane());
configureRootPane(monDialog.getRootPane());
La méthode "configureRootPane" ne devrait être appelée qu'une fois, par exemple juste après l'instanciation de votre conteneur. Il vous reste à implémenter la méthode "onKeyEscape", qui sera appelée lors de chaque appui sur ESCAPE.
|
Consultez les autres F.A.Q's
Les codes sources présentés sur cette page sont libres de droits, et vous pouvez les utiliser à votre convenance. Pour le reste, ce document constitue une oeuvre intellectuelle protégée par les droits d'auteurs.
Ce document issu de http://www.developpez.com est soumis à deux licences, en fonction des contributeurs :
- Les contributions de Clément Cunin et Johann Heymes sont soumises aux termes de la la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies des contributions de Clément Cunin et Johann Heymes tant que cette note apparaît clairement :
"Ce document issu de http://www.developpez.com est soumis à la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement".
- Pour ce qui est des autres contributions : Copyright © 2004 Developpez LLC : Tous droits réservés Developpez LLC. Aucune reproduction, ne peux en être faite sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
|
|
|