10.    Les interfaces graphiques


Ce qui distingue un programme à interface console d’un programme à interface graphique réside principalement dans la notion de programmation événementielle:
•    Dans le premier cas, c’est le programme qui pilote l’utilisateur en le sollicitant au moment voulu pour qu’il fournisse des informations ; le dialogue se fait en mode texte et de façon séquentielle, dans une fenêtre nommée "console".
•    Dans le second cas, au contraire, l’utilisateur a l’impression de piloter le programme qui réagit à des demandes qu’il exprime en sélectionnant des articles de menu, en cliquant sur des boutons, en remplissant des boîtes de dialogue.

10.1    AWT et Swing

Java possède plusieurs packages pour utilisation des interfaces graphiques. Dans ce cours on va discuter Awt et Swing.

Initialement Java ne disposait que du package AWT(Abstract Window Toolkit) qui repose sur des composants dits "lourds" et dépendants du système d’exploitation. Un même composant AWT aura une apparence différente sur différentes plateformes. La portabilité est assurée, mais l’apparence peut être différente à partir du même fichier .class.

Le package Swing propose des composants dits "légers", indépendants du système d’exploitation gérés entièrement par la machine virtuelle , et dotés de propriétés plus riches que ceux de AWT.

Les deux packages utilisent des concepts semblables. Le package Swing utilise une partie des composant de package AWT.


Component                                                             AWT

      Label                                                                 AWT

      Container                                                          AWT

             Panel                                                           AWT

                   Applet                                                  AWT

                         JApplet

             JComponent

                   JLabel

                   JComboBox

                   AbstractButton

                         JButton

                         JToggleButton

                                JCheckBox

                                JRadioButton

                   JMenuItem

                         JMenu

                         JCheckBoxMenuItem

                   JMenuBar

                   JPanel

                   JToolBar

                   JScrollPane

                   JTabbedPane

                   JSplitPane

                   JTextComponent

                         JTextField

                         JTextArea

                         JEditorPane

                   JList

                   JTree

                   JTable

             Window                                                     AWT

                   Frame                                                 AWT

                         JFrame

                   Dialog                                                  AWT

                         JDialog

                   Jwindow

 

Fig. 10.1 Les composants Swing


10.2    La classe JFrame


Pour utiliser une interface graphique l'application doit créer une fenêtre graphique où on peut mettre des différents composants.

10.2.1    Création d’une fenêtre


import javax.swing.* ;
public class Window1 {
    public static void main (String args[]){
        JFrame wd = new JFrame() ;    // constructeur
        wd.setSize (250, 100) ;    //dimensions (position par défault sur le moniteur)
        wd.setTitle ("graphic window") ;
        wd.setVisible (true) ;
    }
}


wd.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);    //ne rien faire
wd.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);        // cacher la fenêtre (comportement par défaut)
wd.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);    // détruire l’objet fenêtre
wd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    // fin à l'application

Dans une autre classe

import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);    //dimensions et position sur le moniteur
        this.setVisible(true);
        this. setTitle ("graphic window") ;
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}


-------------------------------------------------------
public class Test {
    public static void main(String arg[]){
        MyFrame mf = new MyFrame(50,80,200,150);
    }
}

10.2.2    Action sur les caractéristiques d’une fenêtre

import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);
        this.setVisible(true);
        this. setTitle ("graphic window") ;
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
-------------------------------------------------------
import java.util.Scanner;
public class Test1 {
    public static void main(String arg[]){
        Scanner in = new Scanner(System.in);
        MyFrame mf = new MyFrame(50,80,300,250);
        System.out.print("new frame created, enter to change dimensions");
        in.nextLine();
        mf.setSize (350, 300) ;
       
        System.out.print("new name: ");
        String s = in.nextLine();
        mf.setTitle (s);       
        System.out.println("boundaries modified ");
        mf.setBounds(60,45,350,220);      //x, y of the upper left corner, length, height
       
        System.out.print("new length ");
        int ln= Integer.parseInt(in.nextLine());
        System.out.print("new height ");
        int height= Integer.parseInt(in.nextLine());
        mf.setSize (ln,height);
        System.out.print("enter to make invisible:");
        in.nextLine();
        mf.setVisible(false);
        System.out.print("enter to make visible:");
        in.nextLine();
        mf.setVisible(true);
        System.out.print("enter to finish program");
        in.nextLine();
        in.close();
        System.exit(1);
    }
}


10.2.3    Gestion de la souris – entrée, sortie, clic dans la fenêtre

En Java, tout événement possède ce que l’on nomme une source. Il s’agit de l’objet lui ayant donné naissance : bouton, article de menu, fenêtre.

Pour traiter un événement, on a besoin d'un objet, dont la classe implémente une interface particulière correspondant à une catégorie d’événements. On dit que cet objet est un écouteur (listener) de cette catégorie d’événements. Chaque méthode proposée par l’interface correspond à un événement de la catégorie. Ainsi, il existe une catégorie d’événements souris qu’on peut traiter avec un écouteur de souris.

L'interface correspondant s'appelle MouseListener. Cette dernière comporte cinq méthodes correspondant chacune à un événement particulier : mousePressed(), mouseReleased(), mouseEntered(), mouseExited() et mouseClicked().

Une classe interne susceptible d’instancier un objet écouteur de ces différents événements devra donc redéfinir tous les méthodes déclarée dans l'interface MouseListener

class MyMouse implements MouseListener {
    public void mouseClicked (MouseEvent ev) { ..... }
    public void mousePressed (MouseEvent ev) { ..... }
    public void mouseReleased(MouseEvent ev) { ..... }
    public void mouseEntered (MouseEvent ev) { ..... }
    public void mouseExited (MouseEvent ev) { ..... }
    // autres méthodes et champs de la classe
}



import java.awt.event.*;
import javax.swing.* ;
public class MyFrame extends JFrame{
    private static final long serialVersionUID = 1L;
    JLabel l;
    MyFrame(int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);      
        this.addMouseListener(new MyMouse()); 
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        l=new JLabel("to show mouse events",JLabel.CENTER);
        add(l);
        this.setVisible(true);
    }
     public class MyMouse implements MouseListener{
        public void mouseClicked(MouseEvent ev) {
            int x = ev.getX(); int y=ev.getY();
            int xabs=ev.getXOnScreen(); int yabs=ev.getYOnScreen();
            l.setText("in: x= "+x+ " y="+y+" ("+xabs+","+yabs+") on screen");
            if(ev.getClickCount()==2) l.setText(l.getText()+" double clicked");
        }
        public void mousePressed (MouseEvent ev) {}
        public void mouseReleased(MouseEvent ev) {}
        public void mouseEntered (MouseEvent ev) {
            l.setText("mouse in");
        }
        public void mouseExited (MouseEvent ev) {
            l.setText("mouse out");
        }
    }
}

public class Test {
    public static void main(String arg[]){
        new MyFrame(50,80,400,350);
    }
}  


10.2.4    La notion d’adaptateur

Java dispose d’une classe particulière MouseAdapter qui implémente toutes les méthodes de l’interface MouseListener avec un corps vide.

class MouseAdapter implements MouseListener {
    public void mouseClicked (MouseEvent ev) {}
    public void mousePressed (MouseEvent ev) {}
    public void mouseReleased(MouseEvent ev) {}
    public void mouseEntered (MouseEvent ev) {}
    public void mouseExited (MouseEvent ev) {}
}

En utilisant la classe à la place de l'interface on ne doit pas redéfinir des méthodes vides.

public class MyMouse extends MouseAdapter {
    public void mouseClicked(MouseEvent ev) {
        System.out.println("x="+ev.getX() + " y="+ ev.getY());
    }
    public void mouseEntered (MouseEvent ev) {
        System.out.println("mouse in");
    }
    public void mouseExited (MouseEvent ev) {
        System.out.println("mouse out");
    }
}

10.2.5    La gestion des événements en général

En particulier, à une catégorie donnée Xxx, on associera toujours un objet écouteur des événements (de type XxxEvent), par une méthode nommée addXxxListener. Chaque fois qu’une catégorie donnée disposera de plusieurs méthodes, on pourra :
•    soit redéfinir toutes les méthodes de l’interface correspondante XxxListener (la clause implements XxxListener devant figurer dans l’en-tête de classe de l’écouteur), certaines méthodes pouvant avoir un corps vide ;
•    soit faire appel à une classe dérivée d’une classe adaptateur XxxAdapter et ne fournir que les méthodes qui nous intéressent (lorsque la catégorie dispose de plusieurs méthodes).

10.3    La classe JButton


10.3.2    Affichage du bouton, gestionnaire de disposition


import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(String name,int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle(name);
    }
}

import javax.swing.*;
public class Test {
    public static void main(String arg[]){
        MyFrame mf = new MyFrame("ButtonOne",50,80,200,150);
        JButton bt1 = new JButton("butt1");
        mf.add(bt1);                       // Gestionnaire (Layout) par défaut
        mf.validate();                     // validate un conteneur - layout ses composants
    }
}
------------------------------------------------------------------

Pour choisir un gestionnaire, il suffit d’appliquer la méthode setLayout à l’objet contenu de la fenêtre

import java.awt.*;
import javax.swing.*;
public class Test {
    public static void main(String arg[]){
        MyFrame mf =
             new MyFrame("ButtonOne",50,80,200,150);
        mf.setLayout(new FlowLayout());    
        JButton bt1 = new JButton("butt1");
        JButton bt2 = new JButton("butt2");
        mf.add(bt1);
        mf.add(bt2);
        mf.validate();
    }
}

Disparaître temporairement un bouton par setVisible(false),
 Réapparaître par setVisible(true).

10.3.3    Gestion du bouton avec écouteur


import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(String name,int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);
        this.setVisible(true);
        this.setTitle(name);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
-------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test {
    static int cnt1=0,cnt2=0;
    public static void main(String arg[]){
        MyFrame mf = new MyFrame("ButtonOne",50,80,200,150);
        mf.setLayout(new FlowLayout());
        JButton bt1 = new JButton("butt1");     JButton bt2 = new JButton("butt2");
        mf.add(bt1);            
        mf.add(bt2);
        bt1.addActionListener(new Bt1());
        bt2.addActionListener(new Bt2());
        mf.validate();
    }
    static class Bt1 implements ActionListener{
        public void actionPerformed(ActionEvent ev){
            System.out.println("butt1: "+ ++cnt1+" times clicked");          
        }
    }
    static class Bt2 implements ActionListener{
        public void actionPerformed(ActionEvent ev){
            System.out.println("butt2: "+ ++cnt2+" times clicked");          
        }
    }
}

10.3.4    La fenêtre écoute les boutons


import java.awt.event.*;
import javax.swing.* ;
public class MyFrame extends JFrame implements ActionListener{
    int cnt1,cnt2;
    MyFrame(String name,int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle(name);
        cnt1=cnt2=0;
    }
    public void actionPerformed(ActionEvent ev){
        if (ev.getActionCommand().equals("butt1")){
            System.out.println("butt1: "+ ++cnt1+" times clicked");
        }
        if (ev.getActionCommand().equals("butt2")){
            System.out.println("butt2: "+ ++cnt2+" times clicked");
        }
    }
}

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Test {
    static int cnt1=0,cnt2=0;
    public static void main(String arg[]){
        MyFrame mf = new MyFrame("ButtonOne",50,80,200,150);
        mf.setLayout(new FlowLayout());
        JButton bt1 = new JButton("butt1");
        JButton bt2 = new JButton("butt2");
        mf.add(bt1);
        mf.add(bt2);
        bt1.addActionListener(mf);
        bt2.addActionListener(mf);
        mf.validate();
    }
}

10.3.5    La méthode getSource()

Elle s'applique à tous les composants

import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(String name,int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);
        this.setVisible(true);
        this.setTitle(name);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
----------------------------------------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test1 {
    static int cnt1=0,cnt2=0;
    static JButton bt1,bt2;
    static Bt btLs;
    public static void main(String arg[]){
        MyFrame mf = new MyFrame("One Listener",50,80,200,150);
        mf.setLayout(new FlowLayout());
        bt1 = new JButton("butt1");
        bt2 = new JButton("butt2");
        mf.add(bt1);
        mf.add(bt2);
        btLs = new Bt();
        bt1.addActionListener(btLs);
        bt2.addActionListener(btLs);
        mf.validate();
    }
    static class Bt implements ActionListener{
        public void actionPerformed(ActionEvent ev){
            if (ev.getSource() == bt1){
                System.out.println("butt1: "+ ++cnt1+" times clicked");
            }
            if (ev.getSource() == bt2){
                System.out.println("butt2: "+ ++cnt2+" times clicked");
            }
        }
    }
}


10.3.6    La méthode getActionCommand()

Elle s'applique aux composants qui disposent d’une chaîne de commandes - les boutons, les cases à cocher, les boutons radio et les options de menu.

static class Bt implements ActionListener{
    public void actionPerformed(ActionEvent ev){
        if (ev.getActionCommand().equals("butt1")){
            System.out.println("butt1: "+ ++cnt1+" times clicked");
        }
        if (ev.getActionCommand().equals("butt2")){
            System.out.println("butt2: "+ ++cnt2+" times clicked");
        }
    }
}

10.3.7    Dynamique des composants

On peut, à tout instant  créer un nouveau composant ( add(comp) ), supprimer un composant ( remove(comp) ). Il faut forcer le gestionnaire de mise en forme à recalculer les positions des composants dans la fenêtre, de l’une des façons suivantes:
•    en appelant la méthode revalidate() pour le composant concerné;
•    en appelant la méthode validate() (ou repaint() dans certains cas) pour son conteneur.

import java.awt.event.*;
import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(String name,int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);
        this.setVisible(true);
        this.setTitle(name);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
----------------------------------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test {
    static JButton bt=null;
    static MyFrame mf=null,mfc=null;
    public static void main(String arg[]){
        mfc = new MyFrame("ButtonControl",10,80,200,150);
        mfc.setLayout(new FlowLayout());
        mf = new MyFrame("Buttons",10,250,200,150);
        mf.setLayout(new FlowLayout());
        JButton btc1=new JButton("add a new button");
        btc1.addActionListener(new AdBt());
        mfc.add(btc1);
        JButton btc2 = new JButton("remove the button");
        btc2.addActionListener(new RmBt());
        mfc.add(btc2);
        mfc.validate();
    }
    static class AdBt implements ActionListener{       
        public void actionPerformed(ActionEvent arg0) {
            if(bt == null){
                bt = new JButton("added button");
                mf.add(bt);
                mf.validate(); //or bt.revalidate();
            }           
        }
    }
    static class RmBt implements ActionListener{       
        public void actionPerformed(ActionEvent arg0) {
            if(bt != null){
                mf.remove(bt);
                mf.setVisible(false);
                mf.setVisible(true);   // ou mf.repaint();
                bt = null;
            }
        }
    }
}

On peut désactiver un composant (faire en sorte qu’on ne puisse plus agir sur lui), réactiver un composant désactivé  ( setEnabled(true/false)  ).

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyFrame extends JFrame{
    MyFrame(String name){
        this.setBounds(200, 250, 250, 200);
        this.setVisible(true);
        this.setTitle(name);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
//----------------------------------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test {
    static JButton bt[];
    public static void main(String arg[]){
        MyFrame mf = new MyFrame("activate/desactivate");
        bt = new JButton[4];
        mf.setLayout(new FlowLayout());
        Activ act = new Activ();
        bt[0]= new JButton("activate all");
        mf.add(bt[0]);
        bt[0].addActionListener(act);
        for(int i=1;i<bt.length;i++){
            bt[i]= new JButton("desactivate "+ i);
            mf.add(bt[i]);
            bt[i].addActionListener(new Desactiv(i));
        }
        mf.validate();
    }
    static class Desactiv implements ActionListener{
        int n;
        Desactiv(int n){     this.n = n; }
        public void actionPerformed(ActionEvent ev) {
            bt[n].setEnabled (false) ;        
        }       
    }
    static class Activ implements ActionListener{       
        public void actionPerformed(ActionEvent ev) {
            for(int i = 1; i<bt.length; i++){
                bt[i].setEnabled (true) ;
            }                       
        }       
    }
}

10.4    La classe JPanel



Composants intermédiaires qui doivent être contenus dans un conteneur, tout en contenant eux-mêmes d’autres composants.

import java.awt.event.*;
import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(String name,int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);
        this.setVisible(true);
        this.setTitle(name);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test {
    static Button bt1,bt2,bt3,bt4;
    static JPanel jp1,jp2;
    public static void main(String arg[]){
        MyFrame mfc=new MyFrame(
                        "ButtonControl",10,80,200,150);
        mfc.setLayout(new FlowLayout());
        jp1 = new JPanel(new FlowLayout());
        jp2 = new JPanel(new FlowLayout());
        jp1.setBackground(Color.yellow);
        jp2.setBackground(Color.green);
        mfc.add(jp1);
        mfc.add(jp2);
        bt1 = new Button("show green");
        bt2 = new Button("hide green");
        bt3 = new Button("show yellow");
        bt4 = new Button("hide yellow");
        jp1.add(bt1); jp1.add(bt2);
        jp2.add(bt3); jp2.add(bt4);
        bt1.addActionListener(new Show(2));
        bt2.addActionListener(new Hide(2));
        bt3.addActionListener(new Show(1));
        bt4.addActionListener(new Hide(1));
        mfc.validate();
    }
    static class Hide implements ActionListener{
        int npan;
        Hide(int i){this.npan = i;}
        public void actionPerformed(ActionEvent ev) {
            if(npan == 1)jp1.setVisible(false);
            else jp2.setVisible(false);
        }
    }
    static class Show implements ActionListener{
        int npan;
        Show(int i){    this.npan =i;}
        public void actionPerformed(ActionEvent ev) {
            if(npan == 1)jp1.setVisible(true);
            else jp2.setVisible(true);                    }
    }
}


10.5    Dessin sur un composant

10.5.1    Dessins permanents


Pour obtenir que les dessins ne soient modifiés pendant le réaffichage du composant, il est nécessaire de placer les instructions de dessin dans une méthode particulière du composant concerné, nommée paintComponent(). Cette méthode est automatiquement appelée par Java chaque fois que le composant a besoin d’être dessiné ou redessiné.
Il faut aussi appeler explicitement la méthode paintComponent() de la classe ascendante.


import java.awt.event.*;
import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(String nm,int x, int y, int ln, int ht){
        this.setBounds(x, y, ln, ht);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle(nm);
    }
}
----------------------------------------------------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test {
    static JPanel jp1;  
    public static void main(String arg[]){
        MyFrame mfc = new MyFrame(
                "panel draw",10,80,400,300);
        jp1 = new MyPanel();
        mfc.add(jp1);
        mfc.validate();
    }
    static class MyPanel extends JPanel{
        public void paintComponent(Graphics g){
            super.paintComponent(g) ;
            g.drawLine (15, 10, 100, 50) ;
            g.drawLine(100, 50, 150, 10);
            g.drawOval(60, 150, 50, 80);
            g.drawOval(120, 150, 80, 50);
            g.drawRect(240, 150, 80, 80);
            g.drawOval(240, 150, 80, 80);
        }
    }
}   

10.5.2    La méthode repaint()

Lorsqu’un composant a besoin d’être repeint, Java appelle automatiquement sa méthode paintComponent(). Cependant, il peut être amené à limiter le dessin à la seule partie (rectangulaire) du composant qui s’est trouvée endommagée.
On peut forcer le dessin de l’intégralité du composant concerné par appel de repaint(), qui est définit dans la classe de base de tous les composants – Component.

10.5.3    Dessiner en directe

Dessiner en direct - au fur et à mesure des actions de l’utilisateur. Cette démarche est applicable en Java mais à condition d’accepter que la permanence des dessins ne soit plus assurée.  Pour dessiner à la volée sur un composant, il est nécessaire :
•    D’obtenir un contexte graphique pour ce composant en utilisant sa méthode getGraphics() (paintComponent() fournit automatiquement un contexte graphique en argument).
•    D’appliquer les opérations de dessin à ce contexte graphique comme auparavant.
•    De libérer le contexte graphique par dispose(), afin d’éviter d’encombrer inutilement la mémoire (paintComponent() réalisait automatiquement cette libération).

package dessinDirect;
import java.awt.*;
import java.awt.event.*;
import javax.swing.* ;

class MyFrame extends JFrame{
    MyFrame () {
        setTitle ("Clics traces") ;
        setSize (300, 150) ;
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pan = new JPanel() ;
        add(pan) ;
        pan.addMouseListener (new MyListener(pan)) ;
    }
    private JPanel pan ;
}
class MyListener extends MouseAdapter {
    int xPrev=-1,yPrev=-1;
    public MyListener (JPanel pan)    {
        this.pan = pan ;
    }
    public void mouseClicked (MouseEvent ev) {
        int x = ev.getX(), y = ev.getY() ;
        Graphics g = pan.getGraphics() ;
        g.drawRect (x, y, 5, 5) ;
        if(xPrev>=0)g.drawLine(xPrev,yPrev,x,y);
        xPrev=x; yPrev=y;
        g.dispose();
    }
    private JPanel pan ;
}
public class Clics {
    public static void main (String args[]){
        MyFrame mf = new MyFrame() ;
        mf.setVisible(true) ;
    }
}

10.6    Gestion des dimensions


10.6.1    Dimensions de l’écran


import javax.swing.* ;
import java.awt.*;
class MyFrame extends JFrame{
    MyFrame ()         {
        this.setTitle ("Exemple taille fenetre") ;
        Toolkit tk = Toolkit.getDefaultToolkit() ;
        Dimension dimScr = tk.getScreenSize() ;
        this.setSize (dimScr.width/2, dimScr.height/2) ;
        this.setVisible(true);
    }
}
public class Test {
    public static void main(String arg[]){
        MyFrame mf = new MyFrame();
        Dimension dimFrame = mf.getSize();
        System.out.println(dimFrame.width+":"+dimFrame.height);
    }
}


10.6.2    Agir sur la taille préférentielle d’un composant

composant comp :

comp.setPreferredSize(new Dimension (width, height)) ; // largeur width, hauteur height
comp.setMinimumSize(new Dimension (width, height));
comp.setMaximumSize(new Dimension (width, height));

L’effet dépendra du gestionnaire et du type du composant.

10.7    Les cases à cocher

import java.awt.*;
import java.awt.event.*;
import javax.swing.* ;
public class MyFrame extends JFrame{
    MyFrame(String name){
        this.setBounds(10, 10, 150, 120);
        this.setVisible(true);
        this.setLayout(new FlowLayout());
        this.setTitle(name);
        this. setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.* ;
public class Test {
    static JCheckBox chck1,chck2;
    static Vrfy vr = new Vrfy();
    public static void main(String arg[]){
        MyFrame fm=new MyFrame("Chck");
        chck1 = new JCheckBox ("Test",true) ;
        JButton bt1 = new JButton("vtfy");
        chck2 = new JCheckBox ("Test 1") ;    

        JButton bt2 = new JButton("cnvrt");
        fm.add(chck1);
        fm.add(bt1);
        fm.add(chck2);
        fm.add(bt2);
        chck1.addActionListener(vr);
        chck2.addItemListener(new Vrfy1());
        bt1.addActionListener(vr);
        bt2.addActionListener(new Cnvrt());
        fm.validate();
    }
    static class Vrfy implements ActionListener{
        public void actionPerformed(ActionEvent ev){
            System.out.println("Echck1:"+chck1.isSelected());
            System.out.println("Echck2:"+chck2.isSelected()+"\n");
        }
    }
    static class Vrfy1 implements ItemListener{
        public void itemStateChanged (ItemEvent ev){
            System.out.println("Ichck1:"+chck1.isSelected());
            System.out.println("Ichck2:"+chck2.isSelected()+"\n");
        }
    }
    static class Cnvrt implements ActionListener{
        public void actionPerformed(ActionEvent ev){
            if (chck1.isSelected())chck1.setSelected(false);
            else chck1.setSelected(true);
            if (chck2.isSelected())chck2.setSelected(false);
            else chck2.setSelected(true);           
        }
    }
}

10.8    Les boutons radio

JRadioButton bt1 = new JRadioButton ("Test 1") ;                // état non sélectionné
JRadioButton bt2 = new JRadioButton ("Test 2", true) ;        // état sélectionné

Pour la désactivation automatique d’autres boutons radio d’un même groupe, il faut créer un objet de type ButtonGroup et associer chacun des boutons voulus à ce groupe à l’aide de la méthode add():

ButtonGroup grp = new ButtonGroup() ;
grp.add(bt1) ;
grp.add(bt2) ;

10.9    Les étiquettes

JLabel permet d’afficher dans un conteneur un texte (d’une seule ligne) non modifiable par l’utilisateur, mais que le programme peut modifier. Son constructeur précise le texte initial:

JLabel txt = new JLabel ("initial") ;

Le programme peut modifier à tout instant le texte:

txt.setText ("new") ;

10.10    Les champs de texte

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyFrame extends JFrame implements ActionListener,FocusListener{
    JTextField tf1,tf2,tf3;
    JTextArea ta;
    MyFrame(){                                   
        this.setSize(300,300);
        this.setLayout(new FlowLayout());
        tf1 = new JTextField("initial", 10);   
        tf2 = new JTextField(10);
        tf3 = new JTextField(10);
        ta = new JTextArea(15,10);
        tf2.setEditable(false);                   
        this.add(tf1);       
        this.add(tf2);
        this.add(tf3);
        this.add(ta);
        tf3.addActionListener(new AdTa());
        tf1.addActionListener(this) ;           
        tf1.addFocusListener(this) ;    
        this.setVisible(true);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }  
    public void actionPerformed(ActionEvent ev){
        tf2.setText(tf1.getText());
    }
    public void focusGained (FocusEvent e){
        System.out.println("Get focus tf1");      
    }
    public void focusLost (FocusEvent e){
        System.out.println("Lost focus tf1");
    }
    class AdTa implements ActionListener{
        public void actionPerformed(ActionEvent arg0) {
            ta.append(tf3.getText()+"\n");
            tf3.setText("");           
        }      
    }
    public static void main(String arg[]){
        MyFrame mf = new MyFrame();      
    }
}

10.11    Les classes JList et JComboBox

JListe est un composant qui permet de choisir une ou plusieurs valeurs dans une liste prédéfinie.
Un objet de JComboBox (drop-down list) est une façon de forcer l'utilisateur à choisir un seul élément parmi un groupe de possibilités.


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class MyFrame extends JFrame implements ListSelectionListener,ActionListener,ItemListener{
    String s[]= {"one","two","three","four","five","six"};
    JList<String> lst;
    JComboBox<String> lstc,lstce;
    MyFrame(){
        this.setSize(250,200);
        this.setLayout(new FlowLayout());
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        lst = new JList<String> (s) ;
        lst.addListSelectionListener(this);
        lstc = new JComboBox<String>(s);
        lstc.addItemListener(this);
        lstce = new JComboBox<String>(s);
        lstce.addActionListener(this);
        lstce.setEditable(true);
        this.add(lst);
        this.add(lstc);
        this.add(lstce);
        this.setVisible(true);
    }
    public void valueChanged(ListSelectionEvent ev) {
        if (!ev.getValueIsAdjusting()){          //pour eliminer la generation deux fois (press et release)
            System.out.print ("items selected:");
            int obj[] = lst.getSelectedIndices() ;
            for (int i = 0 ; i<obj.length ; i++)
                System.out.print (obj[i]+"\t") ;
            System.out.println () ;
        }
    }
    public void actionPerformed (ActionEvent e){
        System.out.print ("action select: ") ;
        Object obj = lstce.getSelectedItem() ;
        System.out.println ((String) obj) ;
    }
    public void itemStateChanged (ItemEvent e){
        System.out.print ((String) e.getItem()+"\t") ;
        if(e.getStateChange()==1)System.out.println ("selected");
        else System.out.println ("deselected");
    }
    public static void main(String arg[]){
        MyFrame mf = new MyFrame();       
    }
}

 10.12    Les boîtes de dialogue JOptionPane  

public static void showMessageDialog(Component parentComponent, Object message) throws HeadlessException
public static void showMessageDialog(Component parentComponent, Object message, String title, int messageType) throws HeadlessException

Le parametre messageType détermine l'îcone de mesage:

Paramètre

Type d’icône

JOptionPane.ERROR_MESSAGE

Erreur

JOptionPane.INFORMATION_MESSAGE

Information

JOptionPane.WARNING_MESSAGE

Avertissement

JOptionPane.QUESTION_MESSAGE

Question

JOptionPane.PLAIN_MESSAGE

Aucune icône




import javax.swing.JOptionPane;
public class Inp {
    public static void main( String[] args ){
        String name = "",s_age="";
        int age;
        name=JOptionPane.showInputDialog("Please enter your name");
        for(;;){
            s_age=JOptionPane.showInputDialog("How old are You (between 11 and 89)?");
            if(s_age != null){
                age=Integer.parseInt(s_age);
                if((age>10) && (age<90)) break;
            }
            JOptionPane.showMessageDialog(null, "the age is out of range",
                    "error",JOptionPane.ERROR_MESSAGE);
        }
        String msg = "Hello " + name + " next year,you'll be " + (age + 1);
        JOptionPane.showMessageDialog(null, msg);
    }
}

10.13    Les menus

Menus déroulants (en anglais "drop-down")-trois classes :
•    un objet barre de menus – JMenuBar (il ne peut y avoir qu'un seul JMenuBar sur un composant donné);
•    différents objets menu – JMenu, qui seront visibles dans la barre de menus;
•    pour chaque menu, les différentes options, de type JMenuItem, qui le constituent.

import java.awt.*;
import java.awt.event.* ;
import javax.swing.* ;
class MyMenu extends JFrame {
    JMenuBar mb;
    JTextField t;
    public MyMenu () {
        setTitle ("Menu example") ;
        setSize (400, 420) ;
        t = new JTextField(3);
        setLayout(new FlowLayout());
        add(t);
        ActionListener al = new ActionListener() {
            public void actionPerformed(ActionEvent ev){
                t.setText(
                        (ev.getActionCommand()));
            }

        };   
        mb = new JMenuBar() ;
        JMenu[] menus = { new JMenu("menu 1"),
            new JMenu("menu 2"), new JMenu("menu 3")};
        for(int i = 0; i < menus.length; i++)
            mb.add(menus[i]);
        setJMenuBar(mb);
        JMenuItem[] items = {
            new JMenuItem("it1"), new JMenuItem("it2")};
        for(int i = 0; i < items.length; i++){
            items[i].addActionListener(al);
            menus[0].add(items[i]);
        }
        menus[0].addSeparator();
        ButtonGroup group = new ButtonGroup() ;
        JRadioButtonMenuItem bt[] = {
            new JRadioButtonMenuItem("bt1"),
            new JRadioButtonMenuItem("bt2")};
         bt[0].setToolTipText ("attention - radio button!") ; // tooltip
        for(int i = 0; i < bt.length; i++){
            group.add(bt[i]);
            bt[i].addActionListener(al);
            menus[0].add(bt[i]);
        }
        menus[0].addSeparator();
        JCheckBoxMenuItem cb[]= {new JCheckBoxMenuItem("chk1"),
            new JCheckBoxMenuItem("chk2"),new JCheckBoxMenuItem("chk3")};
        for(int i = 0; i < cb.length; i++){
            menus[0].add(cb[i]);
            cb[i].addActionListener(al);
        }
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
    }
    public static void main(String arg[]){
        new MyMenu();
    }
}

Sous options - à la place de JMenuItem il faut utiliser JMenu


10.14    Les bulles d’aide

voir  commentaire tooltip en 10.13


10.16    Les gestionnaires de mise en forme

Le gestionnaire de mise en forme (en anglais "Layout manager") est responsable de la disposition des composants.

10.16.1    Le gestionnaire BorderLayout

import java.awt.*;
import javax.swing.*;

public class Test {  
    public static void main(String a[]){
        JFrame fr = new JFrame("Border Layout");
        fr.setBounds(80, 50, 300, 200);
        fr.setLayout(new BorderLayout());
        fr.add("North", new JButton("North"));
        fr.add("South",new Button("South"));
        fr.add("East",new JButton("East"));
        fr.add("West",new JButton("West"));
        fr.add("Center",new JButton("Center"));
        fr.setVisible(true);       
    }
}

10.16.2    Le gestionnaire FlowLayout

import java.awt.*;
import javax.swing.*;

public class Test { 
    public static void main(String a[]){
        JFrame fr = new JFrame("Flow Layout");
        fr.setBounds(80, 50, 500, 200);
        fr.setLayout(new FlowLayout());
        fr.add(new JButton("First"));
        Button b = new Button("Second");
        b.setPreferredSize(new Dimension(100,40));
        fr.add(b);
        fr.add(new Button("Third"));
        fr.setVisible(true);       
    }
}


10.16.3    Le gestionnaire GridLayout


frame.setLayout (new GridLayout (5, 4)) ;         // 5 lignes, 4 colonnes
frame.setLayout (new GridLayout (5, 4, 15, 10));    //intervalle horizontal de 15, intervalle vertical de 10

import java.awt.*;
import javax.swing.*;
public class Test {   
    public static void main(String a[]){
        JFrame fr = new JFrame("Flow Layout");
        fr.setBounds(80, 50, 500, 200);
        fr.setLayout(new GridLayout(2,3));
        String labels[] = {"(0,0)","(1,0)","(2,0)",
                            "(0,1)","(1,1)","(2,1)"};
        for(int i=0;i<labels.length;++i)
            fr.add(new JButton(labels[i]));
        fr.setVisible(true);       
    }
}

import java.awt.*;
import javax.swing.*;
public class Test {   
    public static void main(String a[]){
        JFrame fr = new JFrame("Flow Layout");
        fr.setBounds(80, 50, 500, 200);
        fr.setLayout(new GridLayout(2,3,15,10));  //intervalle horizontal de 15, intervalle vertical de 10
        String labels[] = {"(0,0)","(1,0)","(2,0)",
                            "(0,1)","(1,1)","(2,1)"};
        for(int i=0;i<labels.length;++i)
            fr.add(new JButton(labels[i]));
        fr.setVisible(true);       
    }
}

10.16.4    Le gestionnaire BoxLayout

import javax.swing.* ;
import java.awt.* ;
import java.awt.event.*;
class MyFrame extends JFrame {
    JButton bt1 ;  JLabel label ;
    Box bHor ;     JTextField txt ;
    public MyFrame () {
        setTitle ("BoxLayout horizontal") ;
        setSize (550, 100) ;
        bHor = Box.createHorizontalBox() ;
        add(bHor) ;
        bt1 = new JButton ("Bouton1") ;
        bHor.add (bt1) ;
        txt = new JTextField (20) ;
        bHor.add (txt) ;
        label = new JLabel ("Hello") ;
        bHor.add(label) ;
        setDefaultCloseOperation(EXIT_ON_CLOSE);;
        setVisible(true);
    }
}
public class GrL{
    public static void main (String args[]){
        MyFrame fm = new MyFrame() ;
    }
}

10.16.5    Le gestionnaire GridBagLayout


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridBag extends JFrame {
    GridBagLayout gridBagLayout = new GridBagLayout();
    GridBag(){
        setTitle("GridBagLayout");
        setLayout(gridBagLayout);
        setSize(300,200);
        JButton gridBagButtons[] = new JButton[9];
        for(int i=0;i<9;++i) gridBagButtons[i] = new JButton("Button"+i);
        int gridx[] = {0,1,2,0,2,0,1,1,0};
        int gridy[] = {0,0,0,1,1,2,2,3,4};
        int gridwidth[] = {1,1,1,2,1,1,1,2,3};
        int gridheight[] = {1,1,1,1,2,2,1,1,1};
        GridBagConstraints gridBagConstraints[] = new GridBagConstraints[9];
        for(int i=0;i<9;++i) {
            gridBagConstraints[i] = new GridBagConstraints();
            gridBagConstraints[i].fill=GridBagConstraints.BOTH;
            gridBagConstraints[i].gridx=gridx[i];
            gridBagConstraints[i].gridy=gridy[i];
            gridBagConstraints[i].gridwidth=gridwidth[i];
            gridBagConstraints[i].gridheight=gridheight[i];
            gridBagLayout.setConstraints(gridBagButtons[i],gridBagConstraints[i]);
            add(gridBagButtons[i]);
        }
        setDefaultCloseOperation(EXIT_ON_CLOSE);;
    }
   
    public static void main(String arg[]){
        GridBag gb = new GridBag();
        gb.setVisible(true);
    }
}

10.16.7    Mise en forme sans gestionnaire (positionnement absolu) 

l'utilisateur choisit la place et les dimensions des composants a la main. Pour le faire il faut suivre les pas suivants:
•    Réglez gestionnaire du conteneur à null en appelant setLayout (null);
•    Pour chaque composant dans le conteneur appelez la méthode setBounds();

Button bt = new Button("bt");
bt.setBounds(x, y, width, height);  //x et y sont coordonées du coin supérieur gauche

•    Faire recalculer le conteneur avec la méthode validate() correspondant.
La création de conteneurs avec des composants à positionnement absolu peuvent causer des problèmes si la fenêtre contenant le conteneur est redimensionnée.


 10.17    Textes et graphiques  

10.17.1    La classe FontMetrics


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Disposition  extends JFrame{
    MyPanel pan;
    public Disposition(){
        setTitle ("Disposition") ;
        setSize (180, 120) ;
        pan = new MyPanel();
        add(pan);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }
    class MyPanel extends JPanel{
        public void paintComponent(Graphics g){
            super.paintComponent(g) ;
            int x=10,y=10;
            String s[] = {"one ","two ","three "};
            FontMetrics fm = g.getFontMetrics();
            for(int i =0;i<s.length;i++){
                g.drawString( s[i],x, y);
                x+=fm.stringWidth(s[i]);
            }
            x=10;
            for(int i =0;i<s.length;i++){
                y+=fm.getHeight();
                g.drawString( s[i],x, y);
            }
        }
    }
    public static void main(String arg[]){
        Disposition d = new Disposition();
    }
}

10.17.2    Choix de police de caractères


En Java, une police se définit par:
•    un nom de famille de police (Helvetica, Arial, Times Roman ...) ;
•    un style: romain (normal), gras ou italique ;
•    une taille, exprimée en "points typographiques" (et non en pixels).

import javax.swing.* ;
import java.awt.* ;
import java.awt.event.*;
class Police extends JFrame {
    JPanel pan;
    Police (){
        setTitle ("Fonts") ;
        setSize (220, 150) ;
        pan = new MyPanel() ;
        add(pan) ;
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }   

    class MyPanel extends JPanel {
        public void paintComponent(Graphics g){
            super.paintComponent(g) ;
            FontMetrics fm = g.getFontMetrics() ;
            String fnts[] = GraphicsEnvironment.getLocalGraphicsEnvironment()
                    .getAvailableFontFamilyNames() ;
            int x=10, y=20;
            g.drawString("by default: "+g.getFont().getFontName()+
                    g.getFont().getSize(),x,y);                                         //defaut police
            y+=fm.getHeight()+10;
            Font fn = new Font ("Serif", Font.BOLD+Font.ITALIC, 20) ;        //police logique
            g.setFont(fn);
            g.drawString (fn.getFontName()+"20", x, y) ;
            fn = new Font(fnts[3],Font.PLAIN, 25);                                //police phisique
            y+=fm.getHeight()+10;
            g.setFont(fn);
            g.drawString (fn.getFontName()+" 25", x, y) ;
        }
    }
    public static void main(String arg[]){
        Police d = new Police();
    }
}

Remarque :

10.17.3    Les objets couleur

Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow

class MyPanel extends JPanel {
        public void paintComponent(Graphics g){
            setForeground(Color.blue);                    //couleur avant plant
            …
            setBackground(Color.yellow);                //couleur fond
            …
            setForeground(new Color(200,80,90));            //couleur construit - RGB, bytes
            …
            g.setColor(Color.magenta);                    //couleur avant plant
        }
}

Remarque :

10.17.5    Affichage d’images


•    GIF (Graphical Interchange Format) : 256 couleurs ;
•    JPEG (Joint Photograhic Expert Group) : plus de 16 millions de couleurs (ce format compressé est plus long à traiter que le précédent).
•    PNG

ImageIcon imIc = new ImageIcon (...) ; // chargement de l’image dans imIc
Image im = imIc.getImage() ;             // im contient la référence à l’objet de type Image correspondant
    …
g.drawImage (im, x, y, null) ;            // x et y sont les coordonnée de coin gauche supérieur d'image
drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer);

L’interface Observer comport une méthode imageUpdate() appelée chaque fois qu’une nouvelle portion de l’image est disponible

L'exemple suivant affiche trois images des fichiers C0.jpg, C1.jpg et C2.jpg. Les fichiers se trouvent dans le répertoire courant

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ImageFrame extends JFrame{
    JPanel pan;
    ImageFrame(){
        setTitle ("Images") ;
        setSize (250, 150) ;
        pan = new MyPanel();
        add(pan);
        addWindowListener(new WndCls());
        setVisible(true);
    }
    class MyPanel extends JPanel {
        public void paintComponent(Graphics g){
            int x=10,y=10;
            super.paintComponent(g) ;
            Image img[]= new Image[3];   
            for(int i=0;i<img.length;i++){
                img[i]=Toolkit.getDefaultToolkit().getImage("C"+i+".jpg");
                g.drawImage(img[i], x, y, 70,100,null);
                x+=80;
            }           
            repaint();
        }
    }
    public class WndCls extends WindowAdapter {
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    }
    public static void main(String arg[]){
        ImageFrame ifm = new ImageFrame();
    }
}



Fig. 10.34 Affichage d'Images