FAQ Java GUIConsultez toutes les FAQ

Nombre d'auteurs : 51, nombre de questions : 152, dernière mise à jour : 29 juin 2013 

 
OuvrirSommaireAWT et SwingGénéralités

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 :

 
Sélectionnez
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 ?

Créé le 9 mai 2002  par Johann Heymes

NONIl 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.

Explication :Avant toute chose, il faut bien comprendre les différence entre Awt et Swing : Quel sont les différences entre Awt et Swing ?.

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).

Image non disponible
  • 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.

Démonstration :

 
Sélectionnez
import javax.swing.*;
import java.awt.*;
 
public class AWTSwing {
        private JComboBox combo; // Composant Swing
        private Button bouton; // Composant AWT
 
        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 !

Créé le 9 mai 2002  par Johann Heymes

Téléchargement : AWTSwing.java

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 :

 
Sélectionnez

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 :

 
Sélectionnez
public void start();

méthode permettant de stopper le processus :

 
Sélectionnez
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 ....

Créé le 24 mars 2002  par Johann Heymes

Téléchargement : Exemple d'utilisation pour faire un compteur.

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.

 
Sélectionnez
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.

Créé le 1er janvier 2004  par Clément Cunin

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.

Créé le 1er avril 2002  par L'équipe Java

Il y a un constructeur de JButton et une méthode qui permettent d'avoir le résultat voulu en donnant l'image en argument sous forme de Icon

 
Sélectionnez
JButton bouton = new JButton(new ImageIcon("images/bouton.gif"));

ou

 
Sélectionnez
bouton.setIcon(new ImageIcon("images/bouton.gif"));
Créé le 3 février 2007  par strab

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.

 
Sélectionnez

JButton printButton = new JButton("Imprimer");
printButton.setForeground(Color.red);
printButton.setFocusPainted(false);
printButton.setBorderPainted(false);
printButton.setContentAreaFilled(false);
Créé le 12 août 2004  par bulbo

Voilà un début de code permettant d'imprimer un Container 'cont'.

 
Sélectionnez
/** 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();
} 
Créé le 2 avril 2002  par L'équipe Java

Pour enregistrer un object de type Component en tant qu'image, il faut commencer par dessinner ce composant dans une BufferedImage puis on va écrire cette image dans un fichier.

Voici un exemple qui permet d'enregistrer un composant sous forme d'image JPeg :

 
Sélectionnez
public void saveImage(Component component, File destination){
	BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);
 
	Graphics2D g2d = image.createGraphics();
 
	if(!component.isOpaque()){
		Color bg = component.getBackground();
		bg = (bg.getAlpha() < 255) ? new Color(bg.getRed(), bg.getGreen(), bg.getBlue()) : bg;
 
		Color color = g2d.getColor();
		g2d.setColor(bg);
		g2d.fillRect(0, 0, component.getWidth(), component.getHeight());
		g2d.setColor(color);
	}
 
	component.paint(g2d);
	g2d.dispose();
 
	try {
		ImageIO.write(image, "jpeg", destination);
	} catch (IOException e) {      
		e.printStackTrace();
	} 
}
Mis à jour le 15 novembre 2008  par fxjtarga, Baptiste Wicht

Symptômes :
La fenêtre est vide ou il est impossible de cliquer sur le moindre composant ou les autres fenêtres du système d'exploitation laissent des trainées grises qui ne se redessinne par sur vos fenêtres ou j'ai l'impression que mon application met du temps à réagir.

Cause :
Ce problème est très classique lors d'un long traitement dans une application graphique. En Java, un Thread est chargé de toutes les opérations liées à l'affichage et à la gestion des évènements, le Thread "Event Dispatching Thread" (en abrégé EDT). Si une application utilise ce Thread 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 mises à jour graphiques (d'une barre de progression par exemple). Typiquement, vous avez du code lié au clic sur une button ou un menu (un ActionListener par exemple) et vous y effectuez de gros calculs ou des Thread.sleep(). Vous ne pouvez pas faire ça, les traitement de l'EDT doivent être le plus bref possible!

Solution :
La solution est assez simple à comprendre : tout traitement long doit être effectué par un autre Thread. En java 5 et supérieur, la classe SwingWorker est très utile pour vous aider à faire ça.

Mis à jour le 6 juin 2009  par Clément Cunin, tchize_

L'Event Dispatch Thread, également appelée EDT, est la Thread dans laquelle l'AWT et Swing font à la fois leur affichage et leur propagation d'événements. Les composants AWT et Swing doivent uniquement être utilisés dans l'EDT. Si un composant est instancié, appelé et manipulé depuis une autre Thread, il peut potentiellement provoquer une erreur dans le programme ou ne pas s'afficher correctement.

L'EDT alterne les cycles d'affichage et les cycles de propagation d'événements. Ainsi quand on gère un événement clavier, souris ou de sélection dans un composant on est assuré que :

  1. On est bien dans l'EDT.
  2. Le composant n'est pas en train de se redessiner. Il sera redessiné dans un cycle d'affichage ultérieur (pas forcément le cycle suivant) si on appelle sa méthode repaint() après le traitement de l'évènement. Il existe cependant des manières d'avoir un rendu immédiat lorsque l'état d'un composant est modifié mais généralement vous ne devriez pas avoir besoin de les utiliser.
Créé le 6 juin 2009  par bouye

Les deux manières de vérifier que le traitement actuel se déroule bien dans l'EDT sont :

  • pour l'AWT, d'invoquer la méthode statique isDispatchThread() de la classe java.awt.EventQueue.
  • Pour Swing, d'invoquer la méthode statique isEventDispatchThread() de la classe javax.swing.SwingUtilities
Créé le 6 juin 2009  par bouye

Tout d'abord, il est bien important de comprendre que tout traitement d'événement, tels que des écouteurs pour le clavier, la souris ou de sélections dans des composants, et implémentés de manière standard se déroule déjà dans l'EDT.

Cependant il peut parfois être nécessaire d'effectuer un traitement "plus tard" de manière à essayer d'attendre un moment où le niveau de charge de l'EDT est moins élevé ou pour laisser le temps à l'interface graphique de faire un affichage préliminaire par exemple. Pour se faire il faut appeler la méthode statique invokeLater() de la classe javax.swing.SwingUtilities. Cette méthode rend immédiatement la main après avoir été invoquée.

Exécuter un traitement plus tard dans l'EDT
Sélectionnez
// Cette méthode retourne immédiatement.
SwingUtilities.invokeLater(new Runnable() {
  /**
   * {@inheritDoc}
   */
  @Override public void run() {
      myButton.setText("Salut le monde !") ;
  }
}) ;

Les traitements longs doivent, quant à eux êtres exécutés dans une autre Thread car ils sont susceptibles de bloquer l'EDT et de rendre votre application lente, voir de faire que votre interface graphique ne se réaffiche plus.

Créé le 6 juin 2009  par bouye

Les traitements longs doivent être lancés hors de l'EDT, pour cela il est possible d'utiliser un autre Thread que l'on lance manuellement ou encore d'utiliser un java.util.Timer.

Attention cependant à penser à vérifier et au besoin à changer la priorité du nouveau Thread car cette dernière hérite automatiquement sa priorité de celle de son Thread parent dans laquelle elle a été créée (le nouveau Thread a la même priorité que l'EDT donc).

Pour Java 6 ou plus, il est recommandé d'utiliser la classe javax.swing.SwingWorker qui offre un framework permettant d'exécuter une tache hors de l'EDT tout en récupérant ses résultats intermédiaires et finaux dans l'EDT. Une implémentation existe pour Java 5 qui est disponible chez SwingLabs.

Créé le 6 juin 2009  par bouye

Il existe deux façons de faire :

  • Utiliser la méthode statique invokeLater() de la classe javax.swing.SwingUtilities. Cette méthode prend en paramètre une instance de la classe Runnable qui sera exécuté ultérieurement. Cette méthode retourne immédiatement après avoir été invoquée.
 
Sélectionnez
// Cette méthode retourne immédiatement.
SwingUtilities.invokeLater(new Runnable() {
/**
 * {@inheritDoc}
 */
@Override public void run() {
    myButton.setText("Salut le monde !") ;
}
}) ;
  • Utiliser la méthode statique invokeAndWait() de la classe javax.swing.SwingUtilities. Cette méthode prend en paramètre une instance de la classe Runnable qui sera exécuté. Cette méthode bloque tant que l'action n'a pas été effectuée ce qui permet, par exemple, de mettre à jour l'interface graphique quand on effectue un traitement depuis une autre Thread et de bloquer jusqu'à ce que la GUI ait été modifié. Cette méthode ne DOIT PAS être appelée de l'EDT même.
 
Sélectionnez

// Cette méthode bloque tant que le traitement EDT n'est pas effectué.
SwingUtilities.invokeAndWait(new Runnable() {
/**
 * {@inheritDoc}
 */
@Override public void run() {
    myButton.setText("Salut le monde !") ;
 }
}) ;

Attention cependant, si elle est mal utilisée, invokeAndWait() peut provoquer des deadlock ; il est donc recommandé d'utiliser la classe javax.swing.SwingWorker à la place.

Créé le 6 juin 2009  par bouye

Pour mieux comprendre le problème : Lors d'un traitement long, l'affichage se fige, que faire ?

Voici deux codes sources Java commentés.
JProgress : la mauvaise méthode (la vôtre ?)
JProgress2 = une solution

Créé le 5 juin 2002  par Johann Heymes

Lien : Didacticiel de Sun sur les JProgressMonitor et les JProgressBars
Téléchargement : JProgress.java
Téléchargement : JProgress2.java

Pour faire cela, il faut utiliser la classe UIManager. Par exemple :

 
Sélectionnez

try {
   UIManager.setLookAndFeel("mon.look.and.Feel");
   //on passe au UIManager le nom complet de la classe du Look and Feel
   //naturellement, celle-ci doit être disponible dans le CLASSPATH
} 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).

 
Sélectionnez

JFrame frame = new JFrame();
frame.setVisible(true);
// etc.
try {
   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
   SwingUtilities.updateComponentTreeUI(frame);
   //force chaque composant de la fenêtre à appeler sa méthode updateUI
} catch (InstantiationException e) {
} catch (ClassNotFoundException e) {
} catch (UnsupportedLookAndFeelException e) {
} catch (IllegalAccessException e) {}
Créé le 12 août 2004  par Ioan Calapodescu

Lien : Comment lister les Look & Feel disponibles ?

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.

 
Sélectionnez

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.

Créé le 12 août 2004  par Ioan Calapodescu

Lien : Comment changer le Look & Feel de mon aplication ?
Téléchargement : Menu Look and Feel


Avant tout affichage, il faut appeler la méthode put(Object, Object) de la classe UIManager. Le 1er paramètre correspond à l'objet à modifier, et le second est la valeur à lui donner.


Par exemple, pour mettre en blanc le fond de tous les JPanel :

 
Sélectionnez
UIManager.put("Panel.background", new ColorUIResource(Color.WHITE));
Créé le 12 janvier 2008  par morph41

Lien : Liste d'éléments modifiables d'un Look And Feel


Metal, Le LookAndFeel par défaut, utilise du texte en gras dans la plupart des composants Swing. Le résultat n'est pas forcément des plus esthétiques.


Heureusement il est possible de rémédier à cela en modifiant la propriété swing.boldMetal, soit directement via la classe UIManager :

 
Sélectionnez

// Ne pas utiliser de texte en gras (LnF Metal) :
UIManager.put("swing.boldMetal", Boolean.FALSE);


Soit en passant par les variables systèmes si l'on n'a pas accès au code source :

 
Sélectionnez

java -Dswing.boldMetal=false ... (les autres paramètres standards)
Mis à jour le 12 janvier 2008  par adiGuba

Lien : Les look and Feel
Lien : Comment modifier un élément du LookAndFeel ?

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 :

 
Sélectionnez
  // - pour une JFrame
  maFrame.getRootPane().setDefaultButton(monBouton)
  // - pour une JDialog
  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) :

 
Sélectionnez
  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();
          }
        });
  }
 
  ...
 
  // - pour une JFrame
  configureRootPane(maFrame.getRootPane());
  // - pour une JDialog
  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.

Créé le 3 avril 2005  par laffreuxthomas

Il faut en fait ajouter le KeyListener au composant permettant l'édition du combo box, en l'occurrence un JTextField :

 
Sélectionnez
Component c = comboBox.getEditor().getEditorComponent() ;
JTextField textField = (JTextField) c ;
textField.addKeyListener( new KeyListener() ) ;
Créé le 16 décembre 2006  par schniouf


Il suffit d'utiliser la méthode setDefaultLocale de la classe JComponent.


Exemple, si j'ai un programme en français mais que je veux avoir tous mes JFileChooser en anglais :

 
Sélectionnez

JFileChooser.setDefaultLocale(new Locale("en","US"));
// ou JFileChooser.setDefaultLocale(Locale.US)
Créé le 26 mai 2007  par Jack Huser


Pour changer le background de certaines lignes d'une Jlist, il faut utiliser un ListCellRenderer personnalisé :

 
Sélectionnez
class MyCellRenderer extends JLabel implements ListCellRenderer {
 
	public Component getListCellRendererComponent(
		JList list,
		Object value,            // value to display
		int index,               // cell index
		boolean isSelected,      // is the cell selected
		boolean cellHasFocus)    // the list and the cell have the focus
	{
		setText(value.toString());
 
		if (isSelected) {
			setBackground(list.getSelectionBackground());
			setForeground(list.getSelectionForeground());
		}
		else {
			setBackground(list.getBackground());
			setForeground(list.getForeground());
		}
 
		// Ici, il faut tester si on veut changer la couleur et changer par la 
		// couleur de notre choix
		if (taCondition == true){
			setBackground(couleur);
		}
 
		setEnabled(list.isEnabled());
		setFont(list.getFont());
		setOpaque(true);
		return this;
	}
}


Après, il suffit d'appliquer ce renderer à la JList :

 
Sélectionnez
JList list = new JList();
list.setCellRenderer(new MyCellRenderer());


et le tour est joué.

Créé le 26 mai 2007  par seiryujay, Baptiste Wicht


Il suffit de changer le Locale de la JVM au démarrage.

 
Sélectionnez

Locale.setDefault(Locale.US);// par exemple si on est en français et que l'on veut l'anglais (USA)

ou

 
Sélectionnez

Locale.setDefault(new Locale("en", "US"));// par exemple si on est en français et que l'on veut de l'anglais  (USA)

En général:

 
Sélectionnez

Locale loc = new Locale(String langue, String pays)

Dans cet exemple, on aura donc les chiffre décimaux avec des points et non des virgules.

Mis à jour le 15 novembre 2008  par Jack Huser

Lien : Classe java.util.Locale

Il y 2 manières de faire pour disposer ses composants en couche ou en niveaux :

  • En utilisant un JLayeredPane. Cette solution est utilisable avec Swing.
  • En utilisant le principe du ZOrder. Cette solution est valable pour AWT et Swing, pour toutes les classes descendant de Container.

Nous allons prendre comme exemple la disposition de deux JLabels l'un au dessus de l'autre.

Premièrement, avec un JLayeredPane :

 
Sélectionnez
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
 
public class CouchesAvecJLayer extends javax.swing.JFrame {
    public CouchesAvecJLayer() {
        initComponents();
    }
 
    private void placeLesCouches(){
        JLayeredPane layered;
        JLabel dessous;
        JLabel dessus;
 
        layered = new JLayeredPane();
        // Comme il n'y a pas vraiment de layout avec un JLayeredPane
        // il faut gérer soi même les tailles et positions.
        layered.setPreferredSize(new java.awt.Dimension(400, 200));
        // (pour simplifier on ne gère pas les positions, tout ira les
        // uns sur les autres).
 
        dessous = new JLabel("en dessous ! (et en partie masqué)");
        dessous.setSize(dessous.getPreferredSize());
        layered.add(dessous, new Integer(0));
        dessus = new JLabel("au dessus !");
 
        // Inutile, pour jouer avec l'opacité de façon à mieux faire
        // apparaitre ce qui est dessus/dessous
        dessus.setOpaque(true);
 
        layered.add(dessus, new Integer(1));
        add(layered);
        pack();
    }
 
  	@SuppressWarnings("unchecked")
  	private void initComponents() {
    	setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
 
    	pack();
  	}                        
 
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                CouchesAvecJLayer couches;
 
                couches = new CouchesAvecJLayer();
                couches.placeLesCouches();
                couches.setVisible(true);
            }
        });
    }
}

Puis en jouant avec le ZOrder des composants :

 
Sélectionnez
import javax.swing.JLabel;
import javax.swing.JPanel;
 
public class CouchesAvecZOrder extends javax.swing.JFrame {
    public CouchesAvecZOrder() {
        initComponents();
    }
 
    private void placeLesCouches(){
        JPanel zpanel;
        JLabel dessous;
        JLabel dessus;
 
        zpanel = new JPanel();
 
        // Le réglage du layout est particulier avec le ZOrder.
        // Pour simplifier on le supprime.
        zpanel.setLayout(null);
 
        zpanel.setPreferredSize(new java.awt.Dimension(400, 200));
        dessus = new JLabel("au dessus !");
 
        // Comme il n'y a plus de layout on doit gérer les tailles.
        dessus.setSize(dessus.getPreferredSize());
 
        // Inutile, pour jouer avec l'opacité de façon à mieux faire
        // apparaitre ce qui est dessus/dessous
        dessus.setOpaque(true);
 
        zpanel.setComponentZOrder(dessus, 0);
        dessous = new JLabel("en dessous ! (et en partie masqué)");
        dessous.setSize(dessous.getPreferredSize());
        zpanel.setComponentZOrder(dessous, 1);
        add(zpanel);
        pack();
    }
 
  	@SuppressWarnings("unchecked")
  	private void initComponents() {
    	setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
 
    	pack();
  	}                        
 
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                CouchesAvecZOrder couches;
 
                couches = new CouchesAvecZOrder();
                couches.placeLesCouches();
                couches.setVisible(true);
            }
        });
    }
}
Créé le 15 novembre 2008  par gifffftane

Ce n'est pas possible.

Pour obtenir un résultat similaire, il faut utiliser la notion de modèle, souvent attachée à un composant swing (JTable, JTree...). Le modèle Action est le plus simple, et permet de stipuler une même fonction à plusieurs boutons, ou autre composant. Il s'utilise simplement par l'AbstractAction.

Pour créer une AbstractAction :

 
Sélectionnez
class QuelleBelleAction extends javax.swing.AbstractAction
  {
    QuelleBelleAction()
    {
      putValue(NAME, "Merci, developpez.net");
    }
 
    @Override
    public void actionPerformed(ActionEvent e)
    {
      System.out.println("BINGO ! ");
    }
  }

Pour l'utiliser sur plusieurs boutons :

 
Sélectionnez
QuelleBelleAction belle = new QuelleBelleAction();
JButton but1 = new JButton(belle);
JButton but2 = new JButton(belle);
paneau.add(but1);
panneau.add(but2);

... les deux boutons réagiront de la même manière, et auront tous les deux le même label. Et, si l'on fait :

 
Sélectionnez

belle.setEnabled(false);

... les deux boutons seront rendus indisponibles simultanément.

On peut de la même façon mettre plusieurs JTable (ou JTree, ou...) apparemment identiques, parce qu'ils ont le même modèle, et non parce que le composant graphique est le même.

Créé le 6 juin 2009  par gifffftane
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 - 2009 Developpez LLC : Tous droits réservés Developpez LLC. Aucune reproduction ne peut 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.