Licence CC BY-NC-SA

Conteneurs, sliders et barres de progression

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

Dans ce chapitre, nous allons voir de nouveaux conteneurs. Ils seront soit complémentaires au JPanel que vous connaissez bien maintenant, soit à tout autre type de conteneur ayant ses propres spécificités.

Il y a plusieurs objets qui peuvent vous aider à mieux gérer le contenu de vos IHM ; ceux qui seront abordés ici vont, je pense, vous rendre un sacré service… Toutefois, laissez-moi vous mettre en garde : ici, nous n'aborderons pas les objets dans le détail, nous ne ferons même qu'en survoler certains. Le fait est que vous êtes dorénavant à même d'approfondir tel ou tel sujet en Java.

Autres conteneurs

L'objet JSplitPane

Avant de vous faire un laïus (un petit, je vous rassure), regardez la figure suivante. Elle représente des fenêtres avec un JSplitPane.

Exemple de JSplitPane avec déplacement du splitter

Cette figure représente l'intérieur d'un objet JFrame. La barre au milieu est un objet déplaçable qui permet d'agrandir une zone tout en rétrécissant celle d'à côté. Ici, dans la première image, la barre est vers la gauche. La deuxième image est prise pendant que je déplace la barre centrale et enfin, la troisième correspond au résultat lorsque j'ai relâché le bouton de ma souris ! Vous pouvez constater que le conteneur de gauche est devenu plus grand, au détriment de celui de droite…

Je vous rassure tout de suite, ce composant est très simple d'utilisation. En fait, les composants abordés dans ce chapitre n'ont rien de compliqué. Je ne vais pas vous faire mariner plus longtemps : l'objet utilisé ici est un JSplitPane. Voici le code source que j'ai utilisé pour avoir le résultat ci-dessus :

 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
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

public class Fenetre extends JFrame {
  //On déclare notre objet JSplitPane
  private JSplitPane split;

  public Fenetre(){
    this.setLocationRelativeTo(null);
    this.setTitle("Gérer vos conteneur");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(200, 200);

    //On crée deux conteneurs de couleurs différentes
    JPanel pan = new JPanel();
    pan.setBackground(Color.blue);

    JPanel pan2 = new JPanel();
    pan2.setBackground(Color.red);

    //On construit enfin notre séparateur
    split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pan, pan2);

    //On le passe ensuite au content pane de notre objet Fenetre
    //placé au centre pour qu'il utilise tout l'espace disponible
    this.getContentPane().add(split, BorderLayout.CENTER);
    this.setVisible(true);
  }

  public static void main(String[] args){
    Fenetre fen = new Fenetre();
  }
}

Vous avez sans doute repéré l'attribut JSplitPane.HORIZONTAL_SPLIT dans le constructeur de l'objet : il sert à spécifier le type de séparation utilisé. Eh oui, il en existe d'autres ! Vous pouvez obtenir une séparation verticale en utilisant l'attribut JSplitPane.VERTICAL_SPLIT, comme à la figure suivante.

Split vertical

Autre point, les deux autres paramètres ne sont pas nécessairement des JPanel. Ici, j'ai utilisé des JPanel, mais vous pouvez en fait utiliser n'importe quelle classe dérivant de JComponent (conteneur, bouton, case à cocher…) : elle n'est pas belle, la vie ?

Je ne vous avais donc pas menti : cet objet est vraiment très simple d'utilisation, mais je ne vais pas vous laisser tout de suite. Vous ne l'avez peut-être pas remarqué mais ces objets ne peuvent pas faire disparaître entièrement les côtés. Dans notre cas, la fenêtre est petite, mais vous aurez peut-être l'occasion d'avoir une grande IHM et d'agrandir ou de rétrécir fréquemment vos contenus.

L'objet JSplitPane dispose d'une méthode qui permet de rendre la barre de séparation « intelligente »… enfin presque. Ladite méthode ajoute deux petits boutons sur votre barre et, lorsque vous cliquerez dessus, fera rétrécir le côté vers lequel pointe la flèche dans le bouton. L'illustration de mes propos se trouve à la figure suivante.

Flèches de positionnement

Pour avoir ces deux boutons en plus sur votre barre, il vous suffit d'invoquer la méthode split.setOneTouchExpandable(true); (mon objet s'appelle toujours split) et le tour est joué ! Amusez-vous à cliquer sur ces boutons et vous verrez à quoi ils servent.

Avant de vous laisser fouiner un peu à propos de cet objet, vous devez savoir que vous pouvez définir une taille de séparateur grâce à la méthode split.setDividerSize(int size) ; la figure suivante vous montre ce que j'ai obtenu avec une taille de 35 pixels.

Agrandissement du splitter

Vous pouvez également définir où doit s'afficher la barre de séparation. Ceci se fait grâce à la méthode setDividerLocation(int location); ou setDividerLocation(double location);.

Avant de vous montrer un exemple de code utilisant cette méthode, vous avez dû comprendre que, vu que cet objet peut accepter en paramètres des sous-classes de JComponent, il pouvait aussi accepter des JSplitPane ! La figure suivante vous montre ce que j'ai pu obtenir.

Multiple splitter

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
44
45
46
47
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

public class Fenetre extends JFrame {

  private JSplitPane split, split2, split3;

  public Fenetre(){
    this.setLocationRelativeTo(null);
    this.setTitle("Gérer vos conteneur");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(200, 200);

    //On crée deux conteneurs de couleurs différentes
    JPanel pan = new JPanel();
    pan.setBackground(Color.blue);      
    JPanel pan2 = new JPanel();
    pan2.setBackground(Color.red);
    JPanel pan3 = new JPanel();
    pan3.setBackground(Color.orange);
    JPanel pan4 = new JPanel();
    pan4.setBackground(Color.YELLOW);
    //On construit enfin notre séparateur
    split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pan, pan4);
    //On place le premier séparateur
    split.setDividerLocation(80);
    split2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pan3, pan2);
    //On place le deuxième séparateur
    split2.setDividerLocation(100);
    //On passe les deux précédents JSplitPane à celui-ci
    split3 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, split, split2);
    //On place le troisième séparateur
    split3.setDividerLocation(80);

    //On le passe ensuite au content pane de notre objet Fenetre
    //placé au centre pour qu'il utilise tout l'espace disponible
    this.getContentPane().add(split3, BorderLayout.CENTER);
    this.setVisible(true);
  }

  public static void main(String[] args){
    Fenetre fen = new Fenetre();
  }   
}

Je pense que vous en savez assez pour utiliser cet objet comme il convient. Nous allons à présent voir un autre objet bien pratique. Il permet d'ajouter un scroll (barre de défilement) à côté de vos conteneurs afin de pouvoir dépasser les limites de ceux-ci.

L'objet JScrollPane

Afin que vous puissiez mieux juger l'utilité de l'objet que nous allons utiliser ici, nous allons voir un nouvel objet de texte : le JTextArea. Cet objet est très simple : c'est une forme de JTextField, mais en plus grand ! Nous pouvons directement écrire dans ce composant, celui-ci ne retourne pas directement à la ligne si vous atteignez le bord droit de la fenêtre.

Pour vérifier si les lettres tapées au clavier sont bien dans notre objet, vous pouvez récupérer le texte saisi grâce à la méthode getText(). Voici un code d'exemple :

 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
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;

public class Fenetre extends JFrame {

  private JTextArea textPane = new JTextArea();

  public Fenetre(){
    this.setLocationRelativeTo(null);
    this.setTitle("Gérer vos conteneur");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(200, 200);

    JButton bouton =  new JButton("Bouton");
    bouton.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        System.out.println("Texte écrit dans le JTextArea : ");
        System.out.println("--------------------------------");
        System.out.println(textPane.getText());            
      }
    });
    //On ajoute l'objet au content pane de notre fenêtre
    this.getContentPane().add(textPane, BorderLayout.CENTER);
    this.getContentPane().add(bouton, BorderLayout.SOUTH);
    this.setVisible(true);
  }

  public static void main(String[] args){
    Fenetre fen = new Fenetre();
  }   
}

Le code est simple et clair, je vous laisse le tester chez vous ! Cependant, les plus curieux d'entre vous l'auront remarqué : si vous écrivez trop de lignes, vous dépassez la limite imposée par le bas de votre fenêtre… Le texte est bien écrit mais vous ne le voyez pas… Exactement comme pour le bord droit. Pour ce genre de problème, il existe ce qu'on appelle des « scrolls ». Ce sont de petit ascenseurs positionnés sur le côté et / ou sur le bas de votre fenêtre et qui vous permettent de dépasser les limites imposées par ladite fenêtre, comme le montre la figure suivante !

Exemple de JScrollPane

Vous voyez le petit ascenseur à droite et en bas de la fenêtre ? Avec ça, finis les problèmes de taille de vos conteneurs ! Voici le code que j'ai utilisé pour obtenir ce résultat :

 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
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Fenetre extends JFrame {

  private JTextArea textPane = new JTextArea();
  private JScrollPane scroll = new JScrollPane(textPane);

  public Fenetre(){
    this.setLocationRelativeTo(null);
    this.setTitle("Gérer vos conteneur");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(200, 200);

    JButton bouton =  new JButton("Bouton");
    bouton.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        System.out.println("Texte écrit dans le JTextArea : ");
        System.out.println("--------------------------------");
        System.out.println(textPane.getText());            
      }
    });

    //On ajoute l'objet au content pane de notre fenêtre
    this.getContentPane().add(scroll, BorderLayout.CENTER);
    //On aurait pu aussi écrire
    //this.getContentPane().add(new JScrollPane(textPane), BorderLayout.CENTER);
    this.getContentPane().add(bouton, BorderLayout.SOUTH);
    this.setVisible(true);
  }

  public static void main(String[] args){
    Fenetre fen = new Fenetre();
  }   
}

L'objet utilisé afin d'avoir un ascenseur s'appelle donc un JScrollPane. Désormais, vous pourrez écrire aussi loin que vous le voulez, vers le bas et vers la droite ! Les ascenseurs apparaissent automatiquement lorsque vous dépassez les limites autorisées. De plus, vous pouvez redéfinir leurs comportements grâce aux méthodes :

  • scroll.setHorizontalScrollBarPolicy(int policy), qui permet de définir le comportement du scroll en bas de votre fenêtre ;
  • scroll.setVerticalScrollBarPolicy(int policy), qui permet de définir le comportement du scroll à droite de votre fenêtre.

Le paramètre de ces méthodes est un entier défini dans la classe JScrollPane, il peut prendre les valeurs suivantes :

  • JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED : le scroll vertical n'est visible que s'il est nécessaire, donc s'il y a dépassement de la taille en hauteur ;
  • JScrollPane.VERTICAL_SCROLLBAR_NEVER : le scroll vertical n'est jamais visible, même si vous dépassez ; en revanche, le conteneur s'allonge tout de même ;
  • JScrollPane.VERTICAL_SCROLLBAR_ALWAYS : le scroll vertical est toujours visible, même si vous ne dépassez pas.

Les mêmes entiers existent pour le scroll horizontal, mais vous devrez alors remplacer VERTICAL par HORIZONTAL ! Vous devez tout de même savoir que cet objet en utilise un autre : un JScrollBar. Les deux barres de défilement sont deux instances de cet objet…

Nous avons vu comment séparer un conteneur, comment agrandir un conteneur, nous allons maintenant voir comment ajouter dynamiquement des conteneurs !

L'objet JTabbedPane

Dans ce chapitre, vous allez apprendre à créer plusieurs « pages » dans votre IHM… Jusqu'à maintenant, vous ne pouviez pas avoir plusieurs contenus dans votre fenêtre, à moins de leur faire partager l'espace disponible.

Il existe une solution toute simple qui consiste à créer des onglets et, croyez-moi, c'est aussi très simple à faire. L'objet à utiliser est un JTabbedPane. Afin d'avoir un exemple plus ludique, j'ai constitué une classe héritée de JPanel afin de créer des onglets ayant une couleur de fond différente… Cette classe ne devrait plus vous poser de problèmes :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Panneau extends JPanel{
  private Color color = Color.white;
  private static int COUNT = 0;
  private String message = "";

  public Panneau(){}
  public Panneau(Color color){
    this.color = color;
    this.message = "Contenu du panneau N°" + (++COUNT);
  }
  public void paintComponent(Graphics g){
    g.setColor(this.color);
    g.fillRect(0, 0, this.getWidth(), this.getHeight());
    g.setColor(Color.white);
    g.setFont(new Font("Arial", Font.BOLD, 15));
    g.drawString(this.message, 10, 20);
  }
}

J'ai utilisé cet objet afin de créer un tableau de Panneau. Chaque instance est ensuite ajoutée à mon objet gérant les onglets via sa méthode add(String title, JComponent comp).

Vous voudriez peut-être disposer du code tout de suite, le voici donc :

 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
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;

public class Fenetre extends JFrame {
  private JTabbedPane onglet;

  public Fenetre(){
    this.setLocationRelativeTo(null);
    this.setTitle("Gérer vos conteneurs");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(400, 200);

    //Création de plusieurs Panneau
    Panneau[] tPan = {   new Panneau(Color.RED), new Panneau(Color.GREEN), new Panneau(Color.BLUE)};

    //Création de notre conteneur d'onglets
    onglet = new JTabbedPane();
    int i = 0;
    for(Panneau pan : tPan){
      //Méthode d'ajout d'onglet
      onglet.add("Onglet n° "+(++i), pan);
      //Vous pouvez aussi utiliser la méthode addTab
      //onglet.addTab("Onglet n° "+(++i), pan);

    }
    //On passe ensuite les onglets au content pane
    this.getContentPane().add(onglet);
    this.setVisible(true);
  }

  public static void main(String[] args){
    Fenetre fen = new Fenetre();
  }   
}

Ce qui a donné le résultat que l'on peut voir à la figure suivante.

Plusieurs onglets

Vous constatez que l'utilisation de cet objet est très simple, là aussi… Je vais tout de même vous présenter quelques méthodes bien utiles. Par exemple, vous pouvez ajouter une image en guise d'icône à côté du titre de l'onglet. Ce qui pourrait nous donner la figure suivante.

Image en titre d'onglet

Le code est identique au précédent, à l'exception de ce qu'il y a dans la boucle :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
for(Panneau pan : tPan){
  //Méthode d'ajout d'onglet    
  onglet.add("Onglet n° "+(++i), pan);
  //On ajoute l'image à l'onglet en cours
  //Les index d'onglets fonctionnent comme les tableaux : ils commencent à 0
  onglet.setIconAt((i - 1), new ImageIcon("java.jpg"));

  //Vous pouvez aussi utiliser la méthode addTab
  //onglet.addTab("Onglet n° "+(++i), new ImageIcon("java.jpg"), pan);
}

Vous avez également la possibilité de changer l'emplacement des en-têtes d'onglets en spécifiant cet emplacement dans le constructeur, comme ceci :

1
2
3
4
5
6
7
8
//Affiche les onglets en bas de la fenêtre
JTabbedPane onglet = new JTabbedPane(JTabbedPane.BOTTOM);

//Affiche les onglets à gauche de la fenêtre
JTabbedPane onglet = new JTabbedPane(JTabbedPane.LEFT);

//Affiche les onglets à droite de la fenêtre
JTabbedPane onglet = new JTabbedPane(JTabbedPane.RIGHT);

La figure suivante vous montre ce que vous pouvez obtenir.

Emplacement des onglets

Vous pouvez aussi utiliser la méthode setTabPlacement(JTabbedPane.BOTTOM); qui a le même effet : ici, la barre d'exploration des onglets sera située en bas du conteneur. Vous avez aussi la possibilité d'ajouter ou de retirer des onglets. Pour ajouter, vous avez deviné comment procéder ! Pour retirer un onglet, nous allons utiliser la méthode remove(int index). Cette méthode parle d'elle-même, elle va retirer l'onglet ayant pour index le paramètre passé.

 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
//CTRL + SHIFT + O pour générer les imports nécessaires

public class Fenetre extends JFrame {
  private JTabbedPane onglet;
  //Compteur pour le nombre d'onglets
  private int nbreTab = 0;

  public Fenetre(){
    this.setLocationRelativeTo(null);
    this.setTitle("Gérer vos conteneurs");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(400, 200);

    //Création de plusieurs Panneau
    Panneau[] tPan = {   new Panneau(Color.RED), new Panneau(Color.GREEN), new Panneau(Color.BLUE)};

    //Création de notre conteneur d'onglets
    onglet = new JTabbedPane();
    for(Panneau pan : tPan){
      //Méthode d'ajout d'onglets
      onglet.addTab("Onglet N°"+(++nbreTab), pan);
    }
    //On passe ensuite les onglets au content pane
    this.getContentPane().add(onglet, BorderLayout.CENTER);

    //Ajout du bouton pour ajouter des onglets
    JButton nouveau = new JButton("Ajouter un onglet");
    nouveau.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        onglet.add("Onglet N°"+(++nbreTab), new Panneau(Color.DARK_GRAY));
      }
    });

    //Ajout du bouton pour retirer l'onglet sélectionné
    JButton delete = new JButton("Effacer l'onglet");
    delete.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        //On récupère l'index de l'onglet sélectionné
        int selected = onglet.getSelectedIndex();
        //S'il n'y a plus d'onglet, la méthode ci-dessus retourne -1
        if(selected > -1)onglet.remove(selected);
      }
    });

    JPanel pan = new JPanel();
    pan.add(nouveau);
    pan.add(delete);

    this.getContentPane().add(pan, BorderLayout.SOUTH);
    this.setVisible(true);
  }

  public static void main(String[] args){
    Fenetre fen = new Fenetre();
  }   
}

Ce qui peut vous donner la même chose que la figure suivante.

Beaucoup, beaucoup d'onglets…

L'objet JDesktopPane combiné à des JInternalFrame

Ces deux objets sont très souvent associés et permettent de réaliser des applications multifenêtres, comme à la figure suivante.

Exemple d'une application multifenê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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//CTRL + SHIFT + O pour générer les imports nécessaires

public class Bureau extends JFrame{
  private static int nbreFenetre = 0;
  private JDesktopPane desktop = new JDesktopPane();
  private static int xy = 10;

  public Bureau(){
    this.setSize(400, 300);
    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JButton ajouter = new JButton("Ajouter une fenêtre interne");
    ajouter.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent event){
        ++nbreFenetre;
        xy += 2;
        desktop.add(new MiniFenetre(nbreFenetre), nbreFenetre);
      }
    });

    this.getContentPane().add(desktop, BorderLayout.CENTER);
    this.getContentPane().add(ajouter, BorderLayout.SOUTH);            
  }

  class MiniFenetre extends JInternalFrame{
    public MiniFenetre(int nbre){
      this.setTitle("Fenetre N°"+nbre);
      this.setClosable(true);
      this.setResizable(true);
      this.setSize(150, 80);
      this.setLocation(xy, xy);
      this.setVisible(true);
    }      
  }

  public static void main(String[] args){
    Bureau bureau = new Bureau();
    bureau.setVisible(true);
  }   
}

L'objet JWindow

Pour faire simple, c'est une JFrame, mais sans les contours permettant de réduire, fermer ou agrandir la fenêtre ! Il est souvent utilisé pour faire des splash screens (ce qui s'affiche au lancement d'Eclipse, par exemple…).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
//CTRL + SHIFT + O pour générer les imports nécessaires

public class Window extends JWindow{

  public static void main(String[] args){
    Window wind = new Window();
    wind.setVisible(true);
  }

  public Window(){      
    setSize(220, 165);
    setLocationRelativeTo(null);      
    JPanel pan = new JPanel();
    JLabel img = new JLabel(new ImageIcon("planète.jpeg"));
    img.setVerticalAlignment(JLabel.CENTER);
    img.setHorizontalAlignment(JLabel.CENTER);      
    pan.setBorder(BorderFactory.createLineBorder(Color.blue));
    pan.add(img);
    getContentPane().add(pan);
  }
}

Le JEditorPane

Voici un objet sympathique mais quelque peu limité par la façon dont il gère son contenu HTML (voir figure suivante) ! Il permet de réaliser des textes riches (avec une mise en page). Il y a aussi le JTextPane qui vous permet très facilement de faire un mini-éditeur de texte (enfin, tout est relatif…).

Aperçu de l'objet JEditorPane

 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
//CTRL + SHIFT + O pour générer les imports nécessaires

public class Fenetre extends JFrame {
  private JEditorPane editorPane, apercu;
  private JTabbedPane onglet = new JTabbedPane();

  public Fenetre(){
    this.setSize(600, 400);
    this.setTitle("Conteneur éditable");
    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    editorPane = new JEditorPane();
    editorPane.setText(" <HTML><HEAD></HEAD><BODY></BODY></HTML> ");

    apercu = new JEditorPane();
    apercu.setEditable(false);

    onglet.addTab("Editeur HTML", new JScrollPane(editorPane));
    onglet.addTab("Aperçu", new JScrollPane(apercu));
    onglet.addChangeListener(new ChangeListener(){

      public void stateChanged(ChangeEvent e) {            
        FileWriter fw = null;            
        try {
          fw = new FileWriter(new File("tmp/tmp.html"));
          fw.write(editorPane.getText());
          fw.close();
        } catch (FileNotFoundException e1) {
          e1.printStackTrace();
        } catch (IOException e1) {
          e1.printStackTrace();
        }
        try {
          File file = new File("tmp/tmp.html");
          apercu.setEditorKit(new HTMLEditorKit());               
          apercu.setPage(file.toURL());
        } catch (IOException e1) {
          e1.printStackTrace();
        }             
      }            
    });

    this.getContentPane().add(onglet, BorderLayout.CENTER);
    this.setVisible(true);
  }

  public static void main(String[] args){
    Fenetre fen = new Fenetre();
  }   
}

Dans cet exemple, on édite le code HTML dans l'onglet d'édition et, au changement d'onglet, on génère un fichier temporaire avec l'extension .html. Ce fichier est stocké dans un répertoire nommé « tmp » à la racine de notre projet.

Le JSlider

Ce composant vous permet d'utiliser un système de mesure pour une application : redimensionner une image, choisir le tempo d'un morceau de musique, l'opacité d'une couleur, etc. La figure suivante montre à quoi il ressemble.

Un JSlider

Le code source :

 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
//CTRL + SHIFT + O pour générer les imports nécessaires
public class Slide extends JFrame{
  private JLabel label = new JLabel("Valeur actuelle : 30");   
  public Slide(){
    this.setSize(250, 150);
    this.setTitle("Slider");
    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JSlider slide = new JSlider();

    slide.setMaximum(100);
    slide.setMinimum(0);
    slide.setValue(30);
    slide.setPaintTicks(true);
    slide.setPaintLabels(true);
    slide.setMinorTickSpacing(10);
    slide.setMajorTickSpacing(20);
    slide.addChangeListener(new ChangeListener(){
      public void stateChanged(ChangeEvent event){
        label.setText("Valeur actuelle : " + ((JSlider)event.getSource()).getValue());
      }
    });      
    this.getContentPane().add(slide, BorderLayout.CENTER);
    this.getContentPane().add(label, BorderLayout.SOUTH);      
  }   
  public static void main(String[] args){
    Slide slide = new Slide();
    slide.setVisible(true);
  }   
}

La JProgressBar

Elle vous permet de réaliser une barre de progression pour des traitements longs. La figure suivante en est un exemple.

Une JProgressBar

Voici le code source :

 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
//CTRL + SHIFT + O pour générer les imports nécessaires
public class Progress extends JFrame{
  private Thread t;
  private JProgressBar bar;
  private JButton launch ;

  public Progress(){      
    this.setSize(300, 80);
    this.setTitle("*** JProgressBar ***");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);      

    t = new Thread(new Traitement());
    bar  = new JProgressBar();
    bar.setMaximum(500);
    bar.setMinimum(0);
    bar.setStringPainted(true);

    this.getContentPane().add(bar, BorderLayout.CENTER);

    launch = new JButton("Lancer");
    launch.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent event){
        t = new Thread(new Traitement());
        t.start();            
      }
    });      
    this.getContentPane().add(launch, BorderLayout.SOUTH);      
    t.start();      
    this.setVisible(true);      
  }

  class Traitement implements Runnable{   
    public void run(){
      launch.setEnabled(false);

      for(int val = 0; val <= 500; val++){
        bar.setValue(val);
        try {
          t.sleep(10);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
        e.printStackTrace();
        }
      }
      launch.setEnabled(true);
    }   
  }

  public static void main(String[] args){
    Progress p = new Progress();
  }   
}

La modification des valeurs de cet objet doit se faire dans un thread, sinon vous aurez une barre vide, un temps d'attente puis la barre remplie, mais sans que les valeurs aient défilé en temps réel !

Enjoliver vos IHM

Nous n'avons pas beaucoup abordé ce point tout au long du livre, mais je vous laisse découvrir les joyeusetés qu'offre Java en la matière… Voici comment ajouter des bordures à vos composants :

 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
//CTRL + SHIFT + O pour générer les imports nécessaires
public class BorderDemo extends JFrame{

  private String[] list = {   
    "Bevel Border", 
    "Etched Border", 
    "Line Border", 
    "Matted Border", 
    "Raised Bevel Border", 
    "Title Border",
    "Compound Border"
  };

  private Border[] listBorder = {   
    BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.black, Color.red),
    BorderFactory.createEtchedBorder(Color.BLUE, Color.GRAY),
    BorderFactory.createLineBorder(Color.green),
    BorderFactory.createMatteBorder(5, 2, 5, 2, Color.MAGENTA),
    BorderFactory.createRaisedBevelBorder(),
    BorderFactory.createTitledBorder("Titre"),
    BorderFactory.createCompoundBorder(
      BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.black, Color.blue), 
      BorderFactory.createMatteBorder(5, 2, 5, 2, Color.MAGENTA)
    )
  };

  public BorderDemo(){      
    this.setTitle("Les bordures font la fête !");
    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(550, 200);

    JPanel pan = new JPanel();
    for(int i = 0; i < list.length; i++){      
      JLabel lib = new JLabel(list[i]);
      lib.setPreferredSize(new Dimension(150, 50));
      lib.setBorder(listBorder[i]);
      lib.setAlignmentX(JLabel.CENTER);
      lib.setHorizontalAlignment(JLabel.CENTER);
      pan.add(lib);
    }

    this.getContentPane().add(pan);
  }  

  public static void main(String[] args){
    BorderDemo demo = new BorderDemo();
    demo.setVisible(true);
  }   
}

Ce qui nous donne la figure suivante.

Exemples de bordures


  • L'objet JSplitPane vous permet de scinder un conteneur en deux parties via un splitter déplaçable.
  • Vous pouvez spécifier si le splitter doit être horizontal ou vertical.
  • L'objet JScrollPane vous permet d'avoir un conteneur ou un objet contenant du texte de s'étirer selon son contenu, en hauteur comme en largeur.
  • L'objet JTabbedPane vous permet d'obtenir une interface composée d'autant d'onglets que vous le désirez et gérable de façon dynamique.
  • Vous pouvez donner un titre et même une image à chaque onglet.
  • Les onglets peuvent être disposés aux quatre coins d'une fenêtre.
  • Les objets JDesktopPane combinés à des objets JInternalFrame vous permettent de créer une application multifenêtre.
  • L'objet JWindow est une JFrame sans les contrôles d'usage. Elle sert à afficher une image de lancement de programme, comme Eclipse par exemple.
  • L'objet JEditorPane vous permet de créer un éditeur HTML et d'afficher le rendu du code écrit.
  • Vous pouvez gérer des mesures ou des taux via l'objet JSlider. En déplaçant le curseur, vous pourrez faire croître une valeur afin de l'utiliser.
  • L'objet JProgressBar affiche une barre de progression.
  • Vous pouvez enjoliver la plupart de vos composants avec des bordures en utilisant l'objet BorderFactory qui vous permettra de créer différents types de traits.