Positionner des boutons

Ce contenu est obsolète. Il peut contenir des informations intéressantes mais soyez prudent avec celles-ci.

Voici l'un des moments que vous attendiez avec impatience ! Vous allez enfin pouvoir utiliser un bouton dans votre application. Cependant, ne vous réjouissez pas trop vite : vous allez effectivement insérer un bouton, mais vous vous rendrez rapidement compte que les choses se compliquent dès que vous employez ce genre de composant… Et c'est encore pire lorsqu'il y en a plusieurs !

Avant de commencer, nous devrons apprendre à positionner des composants dans une fenêtre. Il nous faut en effet gérer la façon dont le contenu est affiché dans une fenêtre.

Utiliser la classe JButton

Comme indiqué dans le titre, nous allons utiliser la classe JButton issue du package javax.swing. Au cours de ce chapitre, notre projet précédent sera mis à l'écart : oublions momentanément notre objet Panneau.

Créons un nouveau projet comprenant :

  • une classe contenant une méthode main que nous appellerons Test ;
  • une classe héritée de JFrame (contenant la totalité du code que l'on a déjà écrit, hormis la méthode go()), nous la nommerons Fenetre.

Dans la classe Fenetre, nous allons créer une variable d'instance de type JPanel et une autre de type JButton. Faisons de JPanel le content pane de notre Fenetre, puis définissons le libellé (on parle aussi d'étiquette) de notre bouton et mettons-le sur ce qui nous sert de content pane (en l'occurrence, JPanel).

Pour attribuer un libellé à un bouton, il y a deux possibilités :

1
2
3
4
5
6
//Possibilité 1 : instanciation avec le libellé
JButton bouton = new JButton("Mon premier bouton");

//Possibilité 2 : instanciation puis définition du libellé
JButton bouton2 = new JButton();
bouton2.setText("Mon deuxième bouton");

Il ne nous reste plus qu'à ajouter ce bouton sur notre content pane grâce à la méthode add() de l'objet JPanel. Voici donc notre code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Fenetre extends JFrame{
  private JPanel pan = new JPanel();
  private JButton bouton = new JButton("Mon bouton");

  public Fenetre(){
    this.setTitle("Animation");
    this.setSize(300, 150);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    //Ajout du bouton à notre content pane
    pan.add(bouton);
    this.setContentPane(pan);
    this.setVisible(true);
  }       
}

Voyez le résultat en figure suivante.

Affichage d'un JButton

Je ne sais pas si vous avez remarqué, mais le bouton est centré sur votre conteneur ! Cela vous semble normal ? Ça l'est, car par défaut, JPanel gère la mise en page. En fait, il existe en Java des objets qui servent à agencer vos composants, et JPanel en instancie un par défaut.

Pour vous le prouver, je vais vous faire travailler sur le content pane de votre JFrame. Vous constaterez que pour obtenir la même chose que précédemment, nous allons être obligés d'utiliser un de ces fameux objets d'agencement.

Tout d'abord, pour utiliser le content pane d'une JFrame, il faut appeler la méthode getContentPane() : nous ajouterons nos composants au content pane qu'elle retourne. Voici donc le nouveau code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import javax.swing.JButton;
import javax.swing.JFrame;

public class Fenetre extends JFrame{
  private JButton bouton = new JButton("Mon bouton");

  public Fenetre(){
    this.setTitle("Bouton");
    this.setSize(300, 150);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    //On ajoute le bouton au content pane de la JFrame
    this.getContentPane().add(bouton);
    this.setVisible(true);
  }      
}

La figure suivante montre que le résultat n'est pas du tout concluant.

Bouton positionné sur le content pane

Votre bouton est énorme ! En fait, il occupe toute la place disponible, parce que le content pane de votre JFrame ne possède pas d'objet d'agencement. Faisons donc un petit tour d'horizon de ces objets et voyons comment ils fonctionnent.

Positionner son composant : les layout managers

Vous allez voir qu'il existe plusieurs sortes de layout managers, plus ou moins simples à utiliser, dont le rôle est de gérer la position des éléments sur la fenêtre. Tous ces layout managers se trouvent dans le package java.awt.

L'objet BorderLayout

Le premier objet que nous aborderons est le BorderLayout. Il est très pratique si vous voulez placer vos composants de façon simple par rapport à une position cardinale de votre conteneur. Si je parle de positionnement cardinal, c'est parce que vous devez utiliser les valeurs NORTH, SOUTH, EAST, WEST ou encore CENTER. Mais puisqu'un aperçu vaut mieux qu'un exposé sur le sujet, voici un exemple à la figure suivante mettant en œuvre un BorderLayout.

Exemple de BorderLayout

Cette fenêtre est composée de cinq JButton positionnés aux cinq endroits différents que propose un BorderLayout. Voici le code de cette fenêtre :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame; 

public class Fenetre extends JFrame{
  public Fenetre(){
    this.setTitle("Bouton");
    this.setSize(300, 300);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    //On définit le layout à utiliser sur le content pane
    this.setLayout(new BorderLayout());
    //On ajoute le bouton au content pane de la JFrame
    //Au centre
    this.getContentPane().add(new JButton("CENTER"), BorderLayout.CENTER);
    //Au nord
    this.getContentPane().add(new JButton("NORTH"), BorderLayout.NORTH);
    //Au sud
    this.getContentPane().add(new JButton("SOUTH"), BorderLayout.SOUTH);
    //À l'ouest
    this.getContentPane().add(new JButton("WEST"), BorderLayout.WEST);
    //À l'est
    this.getContentPane().add(new JButton("EAST"), BorderLayout.EAST);
    this.setVisible(true);
  }      
}

Ce n'est pas très difficile à comprendre. Vous définissez le layout à utiliser avec la méthode setLayout() de l'objet JFrame ; ensuite, pour chaque composant que vous souhaitez positionner avec add(), vous utilisez en deuxième paramètre un attribut static de la classe BorderLayout (dont la liste est citée plus haut).

Utiliser l'objet BorderLayout soumet vos composants à certaines contraintes. Pour une position NORTH ou SOUTH, la hauteur de votre composant sera proportionnelle à la fenêtre, mais il occupera toute la largeur ; tandis qu'avec WEST et EAST, ce sera la largeur qui sera proportionnelle alors que toute la hauteur sera occupée ! Et bien entendu, avec CENTER, tout l'espace est utilisé.

Vous devez savoir que CENTER est aussi le layout par défaut du content pane de la fenêtre, d'où la taille du bouton lorsque vous l'avez ajouté pour la première fois.

L'objet GridLayout

Celui-ci permet d'ajouter des composants suivant une grille définie par un nombre de lignes et de colonnes. Les éléments sont disposés à partir de la case située en haut à gauche. Dès qu'une ligne est remplie, on passe à la suivante. Si nous définissons une grille de trois lignes et de deux colonnes, nous obtenons le résultat visible sur la figure suivante.

Exemple de rendu avec un GridLayout

Voici le code de cet exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.awt.GridLayout; 
import javax.swing.JButton;
import javax.swing.JFrame;

public class Fenetre extends JFrame{
  public Fenetre(){
    this.setTitle("Bouton");
    this.setSize(300, 300);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    //On définit le layout à utiliser sur le content pane
    //Trois lignes sur deux colonnes
    this.setLayout(new GridLayout(3, 2));
    //On ajoute le bouton au content pane de la JFrame
    this.getContentPane().add(new JButton("1"));
    this.getContentPane().add(new JButton("2"));
    this.getContentPane().add(new JButton("3"));
    this.getContentPane().add(new JButton("4"));
    this.getContentPane().add(new JButton("5"));
    this.setVisible(true);
  }      
}

Ce code n'est pas bien différent du précédent : nous utilisons simplement un autre layout manager et n'avons pas besoin de définir le positionnement lors de l'ajout du composant avec la méthode add().

Sachez également que vous pouvez définir le nombre de lignes et de colonnes en utilisant ces méthodes :

1
2
3
4
GridLayout gl = new GridLayout();
gl.setColumns(2);
gl.setRows(3);
this.setLayout(gl);

Vous pouvez aussi ajouter de l'espace entre les colonnes et les lignes.

1
2
3
4
GridLayout gl = new GridLayout(3, 2);
gl.setHgap(5); //Cinq pixels d'espace entre les colonnes (H comme Horizontal)
gl.setVgap(5); //Cinq pixels d'espace entre les lignes (V comme Vertical) 
//Ou en abrégé : GridLayout gl = new GridLayout(3, 2, 5, 5);

On obtient ainsi la figure suivante.

Ajout d'espaces entre les lignes et les colonnes

L'objet BoxLayout

Grâce à lui, vous pourrez ranger vos composants à la suite soit sur une ligne, soit sur une colonne. Le mieux, c'est encore un exemple de rendu (voir figure suivante) avec un code.

Exemple de BoxLayout

Voici le code correspondant :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Fenetre extends JFrame{

  public Fenetre(){

    this.setTitle("Box Layout");
    this.setSize(300, 120);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);

    JPanel b1 = new JPanel();
    //On définit le layout en lui indiquant qu'il travaillera en ligne
    b1.setLayout(new BoxLayout(b1, BoxLayout.LINE_AXIS));
    b1.add(new JButton("Bouton 1"));

    JPanel b2 = new JPanel();
    //Idem pour cette ligne
    b2.setLayout(new BoxLayout(b2, BoxLayout.LINE_AXIS));
    b2.add(new JButton("Bouton 2"));
    b2.add(new JButton("Bouton 3"));

    JPanel b3 = new JPanel();
    //Idem pour cette ligne
    b3.setLayout(new BoxLayout(b3, BoxLayout.LINE_AXIS));
    b3.add(new JButton("Bouton 4"));
    b3.add(new JButton("Bouton 5"));
    b3.add(new JButton("Bouton 6"));

    JPanel b4 = new JPanel();
    //On positionne maintenant ces trois lignes en colonne
    b4.setLayout(new BoxLayout(b4, BoxLayout.PAGE_AXIS));
    b4.add(b1);
    b4.add(b2);
    b4.add(b3);

    this.getContentPane().add(b4);
    this.setVisible(true);
  }
}

Ce code est simple : on crée trois JPanel contenant chacun un certain nombre de JButton rangés en ligne grâce à l'attribut LINE_AXIS. Ces trois conteneurs créés, nous les rangeons dans un quatrième où, cette fois, nous les agençons dans une colonne grâce à l'attribut PAGE_AXIS. Rien de compliqué, vous en conviendrez, mais vous devez savoir qu'il existe un moyen encore plus simple d'utiliser ce layout : via l'objet Box. Ce dernier n'est rien d'autre qu'un conteneur paramétré avec un BoxLayout. Voici un code affichant la même chose que le précédent :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;

public class Fenetre extends JFrame{

  public Fenetre(){
    this.setTitle("Box Layout");
    this.setSize(300, 120);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);

    //On crée un conteneur avec gestion horizontale
    Box b1 = Box.createHorizontalBox();
    b1.add(new JButton("Bouton 1"));
    //Idem
    Box b2 = Box.createHorizontalBox();
    b2.add(new JButton("Bouton 2"));
    b2.add(new JButton("Bouton 3"));
    //Idem
    Box b3 = Box.createHorizontalBox();
    b3.add(new JButton("Bouton 4"));
    b3.add(new JButton("Bouton 5"));
    b3.add(new JButton("Bouton 6"));
    //On crée un conteneur avec gestion verticale
    Box b4 = Box.createVerticalBox();
    b4.add(b1);
    b4.add(b2);
    b4.add(b3);

    this.getContentPane().add(b4);
    this.setVisible(true);
  } 
}

L'objet CardLayout

Vous allez à présent pouvoir gérer vos conteneurs comme un tas de cartes (les uns sur les autres), et basculer d'un contenu à l'autre en deux temps, trois clics. Le principe est d'assigner des conteneurs au layout en leur donnant un nom afin de les retrouver plus facilement, permettant de passer de l'un à l'autre sans effort. La figure suivante est un schéma représentant ce mode de fonctionnement.

Schéma du CardLayout

Je vous propose un code utilisant ce layout. Vous remarquerez que j'ai utilisé des boutons afin de passer d'un conteneur à un autre et n'y comprendrez peut-être pas tout, mais ne vous inquiétez pas, nous allons apprendre à réaliser tout cela avant la fin de ce chapitre. Pour le moment, ne vous attardez donc pas trop sur les actions : concentrez-vous sur le layout en lui-même.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Fenetre extends JFrame{

  CardLayout cl = new CardLayout();
  JPanel content = new JPanel();
  //Liste des noms de nos conteneurs pour la pile de cartes
  String[] listContent = {"CARD_1", "CARD_2", "CARD_3"};
  int indice = 0;

  public Fenetre(){
    this.setTitle("CardLayout");
    this.setSize(300, 120);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);

    //On crée trois conteneurs de couleur différente
    JPanel card1 = new JPanel();
    card1.setBackground(Color.blue);        
    JPanel card2 = new JPanel();
    card2.setBackground(Color.red);     
    JPanel card3 = new JPanel();
    card3.setBackground(Color.green);

    JPanel boutonPane = new JPanel();
    JButton bouton = new JButton("Contenu suivant");
    //Définition de l'action du bouton
    bouton.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent event){
        //Via cette instruction, on passe au prochain conteneur de la pile
        cl.next(content);
      }
    });

    JButton bouton2 = new JButton("Contenu par indice");
    //Définition de l'action du bouton2
    bouton2.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent event){               
        if(++indice > 2)
          indice = 0;
        //Via cette instruction, on passe au conteneur correspondant au nom fourni en paramètre
        cl.show(content, listContent[indice]);
      }
    });

    boutonPane.add(bouton);
    boutonPane.add(bouton2);
    //On définit le layout
    content.setLayout(cl);
    //On ajoute les cartes à la pile avec un nom pour les retrouver
    content.add(card1, listContent[0]);
    content.add(card2, listContent[1]);
    content.add(card3, listContent[2]);

    this.getContentPane().add(boutonPane, BorderLayout.NORTH);
    this.getContentPane().add(content, BorderLayout.CENTER);
    this.setVisible(true);
  } 
}

La figure suivante correspond aux résultats de ce code à chaque clic sur les boutons.

Schéma du CardLayout

L'objet GridBagLayout

Cet objet est certainement le plus difficile à utiliser et à comprendre (ce qui l'a beaucoup desservi auprès des développeurs Java). Pour faire simple, ce layout se présente sous la forme d'une grille à la façon d'un tableau Excel : vous devez positionner vos composants en vous servant des coordonnées des cellules (qui sont définies lorsque vous spécifiez leur nombre). Vous devez aussi définir les marges et la façon dont vos composants se répliquent dans les cellules… Vous voyez que c'est plutôt dense comme gestion du positionnement. Je tiens aussi à vous prévenir que je n'entrerai pas trop dans les détails de ce layout afin de ne pas trop compliquer les choses.

La figure suivante représente la façon dont nous allons positionner nos composants.

Positionnement avec le GridBagLayout

Imaginez que le nombre de colonnes et de lignes ne soit pas limité comme il l'est sur le schéma (c'est un exemple et j'ai dû limiter sa taille, mais le principe est là). Vous paramétreriez le composant avec des coordonnées de cellules, en précisant si celui-ci doit occuper une ou plusieurs d'entre elles. Afin d'obtenir un rendu correct, vous devriez indiquer au layout manager lorsqu'une ligne se termine, ce qui se fait en spécifiant qu'un composant est le dernier élément d'une ligne, et vous devriez en plus spécifier au composant débutant la ligne qu'il doit suivre le dernier composant de la précédente.

Je me doute que c'est assez flou et confus, je vous propose donc de regarder la figure suivante, qui est un exemple de ce que nous allons obtenir.

Exemple de GridBagLayout

Tous les éléments que vous voyez sont des conteneurs positionnés suivant une matrice, comme expliqué ci-dessus. Afin que vous vous en rendiez compte, regardez comment le tout est rangé sur la figure suivante.

Composition du GridBagLayout

Vous pouvez voir que nous avons fait en sorte d'obtenir un tableau de quatre colonnes sur trois lignes. Nous avons positionné quatre éléments sur la première ligne, spécifié que le quatrième élément terminait celle-ci, puis nous avons placé un autre composant au début de la deuxième ligne d'une hauteur de deux cases, en informant le gestionnaire que celui-ci suivait directement la fin de la première ligne. Nous ajoutons un composant de trois cases de long terminant la deuxième ligne, pour passer ensuite à un composant de deux cases de long puis à un dernier achevant la dernière ligne.

Lorsque des composants se trouvent sur plusieurs cases, vous devez spécifier la façon dont ils s'étalent : horizontalement ou verticalement.

Le moment est venu de vous fournir le code de cet exemple, mais je vous préviens, ça pique un peu les yeux :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Fenetre extends JFrame{

  public Fenetre(){
    this.setTitle("GridBagLayout");
    this.setSize(300, 160);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);

    //On crée nos différents conteneurs de couleur différente
    JPanel cell1 = new JPanel();
    cell1.setBackground(Color.YELLOW);
    cell1.setPreferredSize(new Dimension(60, 40));      
    JPanel cell2 = new JPanel();
    cell2.setBackground(Color.red);
    cell2.setPreferredSize(new Dimension(60, 40));
    JPanel cell3 = new JPanel();
    cell3.setBackground(Color.green);
    cell3.setPreferredSize(new Dimension(60, 40));
    JPanel cell4 = new JPanel();
    cell4.setBackground(Color.black);
    cell4.setPreferredSize(new Dimension(60, 40));
    JPanel cell5 = new JPanel();
    cell5.setBackground(Color.cyan);
    cell5.setPreferredSize(new Dimension(60, 40));
    JPanel cell6 = new JPanel();
    cell6.setBackground(Color.BLUE);
    cell6.setPreferredSize(new Dimension(60, 40));
    JPanel cell7 = new JPanel();
    cell7.setBackground(Color.orange);
    cell7.setPreferredSize(new Dimension(60, 40));
    JPanel cell8 = new JPanel();
    cell8.setBackground(Color.DARK_GRAY);
    cell8.setPreferredSize(new Dimension(60, 40));

    //Le conteneur principal
    JPanel content = new JPanel();
    content.setPreferredSize(new Dimension(300, 120));
    content.setBackground(Color.WHITE);
    //On définit le layout manager
    content.setLayout(new GridBagLayout());

    //L'objet servant à positionner les composants
    GridBagConstraints gbc = new GridBagConstraints();

    //On positionne la case de départ du composant
    gbc.gridx = 0;
    gbc.gridy = 0;
    //La taille en hauteur et en largeur
    gbc.gridheight = 1;
    gbc.gridwidth = 1;
    content.add(cell1, gbc);
    //---------------------------------------------
    gbc.gridx = 1;
    content.add(cell2, gbc);
    //---------------------------------------------
    gbc.gridx = 2;      
    content.add(cell3, gbc);        
    //---------------------------------------------
    //Cette instruction informe le layout que c'est une fin de ligne
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.gridx = 3;  
    content.add(cell4, gbc);
    //---------------------------------------------
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.gridwidth = 1;
    gbc.gridheight = 2;
    //Celle-ci indique que la cellule se réplique de façon verticale
    gbc.fill = GridBagConstraints.VERTICAL;
    content.add(cell5, gbc);
    //---------------------------------------------
    gbc.gridx = 1;
    gbc.gridheight = 1;
    //Celle-ci indique que la cellule se réplique de façon horizontale
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    content.add(cell6, gbc);
    //---------------------------------------------
    gbc.gridx = 1;
    gbc.gridy = 2;
    gbc.gridwidth = 2;
    content.add(cell7, gbc);
    //---------------------------------------------
    gbc.gridx = 3;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    content.add(cell8, gbc);
    //---------------------------------------------
    //On ajoute le conteneur
    this.setContentPane(content);
    this.setVisible(true);      
  }
}

Vous pouvez vous rendre compte que c'est via l'objet GridBagConstraints que tout se joue. Vous pouvez utiliser ses différents arguments afin de positionner vos composants, en voici une liste :

  • gridx : position en x dans la grille.
  • gridy : position en y dans la grille.
  • gridwidth : nombre de colonnes occupées.
  • gridheight : nombre de lignes occupées.
  • weightx : si la grille est plus large que l'espace demandé, l'espace est redistribué proportionnellement aux valeurs de weightx des différentes colonnes.
  • weighty : si la grille est plus haute que l'espace demandé, l'espace est redistribué proportionnellement aux valeurs de weighty des différentes lignes.
  • anchor : ancrage du composant dans la cellule, c'est-à-dire son alignement dans la cellule (en bas à droite, en haut à gauche…). Voici les différentes valeurs utilisables :
    • FIRST_LINE_START : en haut à gauche ;
    • PAGE_START : en haut au centre ;
    • FIRST_LINE_END : en haut à droite ;
    • LINE_START : au milieu à gauche ;
    • CENTER : au milieu et centré ;
    • LINE_END : au milieu à droite ;
    • LAST_LINE_START : en bas à gauche ;
    • PAGE_END : en bas au centre ;
    • LAST_LINE_END : en bas à droite.
  • fill : remplissage si la cellule est plus grande que le composant. Valeurs possibles : NONE, HORIZONTAL, VERTICAL et BOTH.
  • insets : espace autour du composant. S'ajoute aux espacements définis par les propriétés ipadx et ipady ci-dessous.
  • ipadx : espacement à gauche et à droite du composant.
  • ipady : espacement au-dessus et au-dessous du composant.

Dans mon exemple, je ne vous ai pas parlé de tous les attributs existants, mais si vous avez besoin d'un complément d'information, n'hésitez pas à consulter le site d'Oracle.

L'objet FlowLayout

Celui-ci est certainement le plus facile à utiliser ! Il se contente de centrer les composants dans le conteneur. Regardez plutôt la figure suivante.

Exemple de FlowLayout

On dirait bien que nous venons de trouver le layout manager défini par défaut dans les objets JPanel. Lorsque vous insérez plusieurs composants dans ce gestionnaire, il passe à la ligne suivante dès que la place est trop étroite. Voyez l'exemple de la figure suivante.

FlowLayout contenant plusieurs composants

Il faut que vous sachiez que les IHM ne sont en fait qu'une imbrication de composants positionnés grâce à des layout managers. Vous allez tout de suite voir de quoi je veux parler : nous allons maintenant utiliser notre conteneur personnalisé avec un bouton. Vous pouvez donc revenir dans le projet contenant notre animation créée au cours des chapitres précédents. Le but est d'insérer notre animation au centre de notre fenêtre et un bouton en bas de celle-ci, comme le montre la figure suivante.

Bouton et animation dans la même fenêtre

Voici le nouveau code de notre classe Fenetre :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.awt.BorderLayout;
import java.awt.Color; 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Fenetre extends JFrame{
  private Panneau pan = new Panneau();
  private JButton bouton = new JButton("mon bouton");
  private JPanel container = new JPanel();

  public Fenetre(){
    this.setTitle("Animation");
    this.setSize(300, 300);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    container.setBackground(Color.white);
    container.setLayout(new BorderLayout());
    container.add(pan, BorderLayout.CENTER);
    container.add(bouton, BorderLayout.SOUTH);
    this.setContentPane(container);
    this.setVisible(true);    
    go();
  }

  private void go(){  
    //Les coordonnées de départ de notre rond
    int x = pan.getPosX(), y = pan.getPosY();
    //Le booléen pour savoir si l'on recule ou non sur l'axe x
    boolean backX = false;
    //Le booléen pour savoir si l'on recule ou non sur l'axe y
    boolean backY = false;

    //Dans cet exemple, j'utilise une boucle while
    //Vous verrez qu'elle fonctionne très bien
    while(true){
      //Si la coordonnée x est inférieure à 1, on avance
      if(x < 1)backX = false;
      //Si la coordonnée x est supérieure à la taille du Panneau moins la taille du rond, on recule
      if(x > pan.getWidth()-50)backX = true;
      //Idem pour l'axe y
      if(y < 1)backY = false;
      if(y > pan.getHeight()-50)backY = true;

      //Si on avance, on incrémente la coordonnée
      if(!backX)
        pan.setPosX(++x);
      //Sinon, on décrémente
      else
        pan.setPosX(--x);
      //Idem pour l'axe Y
      if(!backY)
        pan.setPosY(++y);
      else
        pan.setPosY(--y);

      //On redessine notre Panneau
      pan.repaint();
      //Comme on dit : la pause s'impose ! Ici, trois millièmes de seconde
      try {
        Thread.sleep(3);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }    
  }  
}

  • Un bouton s'utilise avec la classe JButton présente dans le package javax.swing.
  • Pour ajouter un bouton dans une fenêtre, vous devez utiliser la méthode add() de son content pane.
  • Il existe des objets permettant de positionner les composants sur un content pane ou un conteneur : les layout managers.
  • Les layout managers se trouvent dans le package java.awt.
  • Le layout manager par défaut du content pane d'un objet JFrame est le BorderLayout.
  • Le layout manager par défaut d'un objet JPanel est le FlowLayout.
  • Outre le FlowLayout et le BorderLayout, il existe le GridLayout, le CardLayout, le BoxLayout et le GridBagLayout. La liste n'est pas exhaustive.
  • On définit un layout sur un conteneur grâce à la méthode setLayout().