Vous êtes sur la page 1sur 28

Quelques exemples de graphisme, de gestion

d’événements, de gestion de temps et autres en


Java
version 0.3

Table des matières


1 Notions essentielles 3
1.1 Méthode paint . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Événements souris . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Événements clavier . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4 Affichage d’images externes . . . . . . . . . . . . . . . . . . . . . 9
1.5 Utilisation d’un Timer . . . . . . . . . . . . . . . . . . . . . . . . 10
1.6 Gestion du scintillement . . . . . . . . . . . . . . . . . . . . . . . 11

2 Notions facultatives 14
2.1 Liste chaînée pré-conçue . . . . . . . . . . . . . . . . . . . . . . . 14
2.2 Obtenir les dimensions de l’écran . . . . . . . . . . . . . . . . . . 15
2.3 Obtenir la taille d’un texte . . . . . . . . . . . . . . . . . . . . . 16
2.4 Gérer un fichier texte . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.5 Méthode paint et JPanel . . . . . . . . . . . . . . . . . . . . . . 19
2.6 Mettre une image de fond et/ou superposer plusieurs images/-
widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.7 Gérer un groupe de JRadioButton . . . . . . . . . . . . . . . . . 23
2.8 Tracé d’une fonction . . . . . . . . . . . . . . . . . . . . . . . . . 26

Avertissement :
— Ce qui suit est un résumé des concepts essentiels présentés
dans les transparents de cours disponibles sur moodle.
— Il y a également des notions qui ne sont pas vus en cours mais
qui peuvent vous servir.
— Dans les codes que vous trouverez ci dessous, la méthode main
est incluse dans la classe pour des raisons de lisibilité. N’ou-
bliez pas de l’enlever si vous réutilisez ces codes.
— Pour plus de détails, n’oubliez pas de consulter la Javadoc.

1
— Ce document est en version 0.3. Merci de signaler toutes co-
quilles rencontrées.

2
1 Notions essentielles
1.1 Méthode paint
1.1.1 Principe général
Tous les composants graphiques possèdent une méthode public
void paint(Graphics g)

qui définie leur apparence graphique. Si on veut modifier cette apparence, il faut
surcharger (redéfinir) la méthode paint du composant en appelant des méthodes
de la classe Graphics sur l’objet g.
L’appel de cette méthode ne peut être effectué directement dans le code.
C’est le système de gestion graphique (gérer par le système d’exploitation) qui
fait cet appel à chaque fois que le composant doit être dessiné à l’écran après une
modification ou une occultation. Il est toutefois possible de demander au système
d’exploitation d’appeler la méthode paint dès que possible via l’exécution de
l’instruction suivante :
repaint();

Remarque. L’exemple qui suit redéfinit la méthode paint d’un objet héritant de
JFrame. Pour modifier l’apparence graphique d’un objet héritant de JPanel, on
consultera la sous-section 2.5.
Remarque. Pour plus de détails sur les différentes formes géométriques pouvant
être dessinées, on consultera les transparents du cours ou la javadoc pour les
fonctionnalités plus avancées.

1.1.2 Exemple minimaliste

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

public class PaintJFrame extends JFrame {

public PaintJFrame(int w, int h) {


setSize(w,h);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}

public void paint(Graphics g) {


// dessin d’un rectangle de couleur cyan sur toute la surface du
JFrame
g.setColor( Color.cyan ); // choix de la couleur du crayon
g.fillRect(0,0,getSize().width,getSize().height);

// dessin d’une ligne bleue diagonale


g.setColor( Color.blue); // changement de couleur
int xA = 0; int yA = 0; // coordonnees du debut de la ligne
int xB = getSize().width; int yB = getSize().height; // coordonnees
de la fin de la ligne

3
g.drawLine(xA,yA,xB,yB);

// affichage d’un texte bleu aux coordonnees x=100 et y=100


g.setColor(Color.black); // changement de couleur
g.drawString("Mon texte", 100,100);
}

public static void main(String[] args) {


PaintJFrame maFenetre = new PaintJFrame(600,400);
}
}

4
1.2 Événements souris
1.2.1 Principe général
Comme dans le cas des événements boutons (revoir le cours sur la program-
mation événementielle), l’idée consiste à créer un écouteur captant les événe-
ments générés par les mouvements de la souris. Cet écouteur est associé à un
composant graphique (JFrame, JPanel, etc). Des événements seront alors générés
lorsque la souris se déplacera au dessus de ce composant. Plus de détails dans
la javadoc.
Plus précisément, la démarche est la suivante :
— indiquer que votre classe va implémenter l’interface MouseListener
— redéfinir toutes les méthodes de l’interface MouseListener (même si cer-
taines n’ont rien de particulier à faire) :
// Méthode appelée quand le bouton de la souris a été pressée
public void mousePressed(MouseEvent e) { ... }
// Méthode appelée quand le bouton de la souris a été relâchée
public void mouseReleased(MouseEvent e) { ... }
// Méthode appelée quand la souris passe sur le composant
public void mouseEntered(MouseEvent e) { ... }
// Méthode appelée quand la souris sort du composant
public void mouseExited(MouseEvent e) { ... }
// Méthode appelée quand le bouton de la souris a été cliquée
(appuyée puis relâchée)
public void mouseClicked(MouseEvent e) { ... }

— associer l’écouteur au composant désiré (this représente ici le JFrame en


cours) :
addMouseMotionListener(this);

Remarque. Pour capter les événements générés par les mouvements de sou-
ris (et non les clicks), le principe est identique mais l’interface à utiliser est
MouseMotionListener au lieu de MouseListener.

1.2.2 Exemple minimaliste

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

public class EventSouris extends JFrame implements MouseListener{

public EventSouris(int w, int h) {


setSize(w,h);
// branchement de l’ecouteur a la JFrame
addMouseListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}

// Il est nécessaire d’implémenter toutes les méthodes suivantes

5
// même si elles sont vides car elles sont abstraites

public void mouseReleased(MouseEvent e){}


public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){}

public void mouseClicked(MouseEvent e){


System.out.println("Vous avez clique sur la souris");
String s = "("+e.getX()+","+e.getY()+")";
setTitle(s);
}

public static void main(String[] args) {


EventSouris mafenetre = new EventSouris(600,400);
}

6
1.3 Événements clavier
1.3.1 Principe général
La démarche est très similaire à celle présentée pour le cas des événements
souris (à ceci près que l’interface est KeyListener au lieu de MouseListener). Plus
de détails dans la javadoc.
La démarche est la suivante :
— indiquer que votre classe va implémenter l’interface KeyListener.
— redéfinir toutes les méthodes de l’interface KeyListener (même si certaines
n’ont rien de particulier à faire) :
// méthode exécutée à chaque fois qu’une touche est enfoncée
public void keyPressed(KeyEvent e) { ... }
// méthode exécutée à chaque fois qu’une touche est relâchée
public void keyReleased(KeyEvent e) { ... }
// méthode exécutée à chaque fois qu’une touche unicode est
utilisée (donc pas CTRL, SHIFT ou ALT par exemple)
public void keyTyped(KeyEvent e) { ... }

— associer l’écouteur au composant désiré (this représente ici le JFrame en


cours) :
addKeyListener(this);

Remarque. Pour identifier la touche du clavier à l’origine de l’événement, il suffit


de récupérer son code via e.getKeyCode() et de le comparer aux constantes de
la classe KeyEvent comme, par exemple, KeyEvent.VK_DOWN pour la touche bas,
KeyEvent.VK_SPACE pour la touche espace, etc. Plus de détails sur la javadoc.

1.3.2 Exemple minimaliste

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

public class EventClavier extends JFrame implements KeyListener{

public EventClavier() {
setSize(100,100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

addKeyListener(this);

setVisible(true);
}

public void keyPressed(KeyEvent e) {


int code = e.getKeyCode();
System.out.print("Code clavier "+code+" appuye. ");
if (code == KeyEvent.VK_SPACE)
System.out.print("C’est la barre d’espace. ");
else if (code == KeyEvent.VK_DOWN)

7
System.out.print("C’est la fleche du bas. ");
else
System.out.print("Ce n’est ni espace, ni bas. ");
}

public void keyReleased(KeyEvent e) {


System.out.println("Touche relachee.");
}

public void keyTyped(KeyEvent e) {


System.out.println("Touche relachee.");
}

public static void main(String[] args) {


EventClavier evf = new EventClavier();
}
}

8
1.4 Affichage d’images externes
1.4.1 Principe général
L’affichage d’une image externe se fait en deux étapes :
1. chargement de l’image en mémoire à partir de son nom (le fichier doit
être dans le répertoire courant) :
Toolkit T = Toolkit.getDefaultToolkit();
Image im = T.getImage("insa_logo.png");

2. affichage proprement dit en insérant, dans la méthode paint, le code


suivant :
int x = 200; int y = 100; // position de l’image
g.drawImage( im,x,y,null );

Remarque. Comme l’illustre l’exemple qui suit, il est conseillé de charger l’image
en mémoire une seule fois et en dehors de la méthode paint (qui sera fréquem-
ment appelée), afin de réduire le temps d’exécution.

1.4.2 Exemple minimaliste

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

public class AfficheImage extends JFrame{

public Image im;

public AfficheImage(int w, int h) {


setSize(w,h);

// chargement de l’image
Toolkit T=Toolkit.getDefaultToolkit();
im = T.getImage("insa_logo.png");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
repaint(); // demande d’appel de la méthode paint
}

public void paint(Graphics g) {


int x = 200; int y = 100;
g.drawImage( im,x,y,null );
}

public static void main(String[] args) {


AfficheImage mafenetre = new AfficheImage(400,200);
}
}

9
1.5 Utilisation d’un Timer
1.5.1 Principe général
La classe Timer permet de commander l’exécution d’une méthode à intervalle
de temps régulier. Le constructeur de Timer
public Timer(int delay, ActionListener listener)

crée une instance qui exécutera, tous les delay millisecondes, la méthode actionPerformed
de l’instance qui implémente l’interface ActionListener.
Dans l’exemple ci dessous, il y a une boucle infinie dans la méthode main pour
simplifier le code. Il est possible de mettre en pause le Timer t avec l’instruction
t.stop().
Remarque. Il existe une méthode qui permet de savoir si le Timer est en cours
ou en pause. Soit t une instance de Timer, t.isRunning() retourne false si t est
en pause et true sinon.

1.5.2 Exemple minimaliste

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

public class MonTimerInfini implements ActionListener {

// Les attributs de la classe


public long temps;
public int interval;

public MonTimerInfini(int interval){


this.interval=interval;
Timer t = new Timer(interval, this); // Création du timer
temps = 0; // On initialise le temps à 0
t.start(); // On lance le chrono
}

// Méthode exécutée à chaque réveil du Timer


public void actionPerformed(ActionEvent e) {
temps+=interval; // On incrémente le temps
System.out.println("Je suis vivant depuis "+temps+" ms");
}

public static void main(String[] args) {


MonTimerInfini chrono = new MonTimerInfini(100);
while(true);
}
}

10
1.6 Gestion du scintillement
1.6.1 Principe général
Lors de l’exécution de la méthode paint, si le temps qui sépare le dessin du
premier objet graphique (ligne, rectangle...) du dernier est trop long, l’écran peut
scintiller. Typiquement, ce problème apparaît lorsque l’algorithme permettant
de définir l’apparence graphique d’un composant est progressif (le dessin se
fait tout au long de l’algorithme) et exigeant (en terme de temps de calcul).
L’exemple avec scintillement qui suit illustre cette difficulté puisque l’appel de
la méthode paint demande l’exécution de la méthode dessineLourd qui requière
le parcours (exigeant en terme de calcul) de la double boucle suivante :
for(int i=0;i<d.width;i++)
for(int j=0;j<d.height;j++)
g.drawLine(i,j,i,j);

L’exemple sans scintillement résout ce problème en exécutant la méthode


paint en deux temps :
1. exécution de l’algorithme produisant le dessin (une sorte de pré-calcul)
qui est stocké en mémoire dans un buffer (sans être affiché) en donnant
comme paramètre de la méthode dessineLourd, non pas g le paramètre
de la méthode paint, mais l’instance de la classe Graphics associée au
buffer et récupérer via monBuf.getGraphics() :
dessineLourd(monBuf.getGraphics());

2. affichage de ce dessin “d’un seul coup” en lisant le buffer :


g.drawImage(monBuf,0,0,null);

Comparer attentivement les deux codes suivants (avec et sans scintillement)


pour bien comprendre comment s’utilise un buffer d’affichage.

1.6.2 Exemple minimaliste avec scintillement

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

public class BufferScintillement extends JFrame {

private boolean b; // utile pour l’alternance des couleurs

public BufferScintillement(int w, int h) {


setSize(w,h);
b = true;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}

public void paint(Graphics g) {


dessineLourd(g); // dessin dans g

11
}

/*
* Cette methode fait un calcul exigeant en calcul puisqu’elle
* dessine point par point un rectangle sur toute la surface
d’affichage
* dont la couleur alterne entre rouge et noir.
*/
public void dessineLourd(Graphics g) {
Dimension d = getContentPane().getSize(); // dimension de la zone
d’affichage
// alternance de la couleur d’affichage
if (b)
g.setColor(Color.black);
else
g.setColor(Color.red);
b = !b;
// dessin de toute la zone d’affichage point par point
for(int i=getInsets().left;i<d.width;i++)
for(int j=getInsets().top;j<d.height;j++)
g.drawLine(i,j,i,j); // ligne commencant et terminant au meme
point
}

public static void main(String[] args) {


BufferScintillement mafenetre = new BufferScintillement(1000,600);
for(int i=1;i<100;i++) {
// pause de 500 ms
try {
Thread.sleep(500);
} catch(InterruptedException e) {};
// demande d’appel de la methode paint
mafenetre.repaint();
}
}
}

1.6.3 Exemple minimaliste sans scintillement

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class BufferAntiScintillement extends JFrame {

private BufferedImage monBuf; // buffer d’affichage


private boolean b;

public BufferAntiScintillement(int w, int h) {


setSize(w,h);
b = true;

// initialisation du buffer

12
Dimension dim = getSize(); // recupere la taille reelle de la
fenetre
monBuf = new
BufferedImage(dim.width,dim.height,BufferedImage.TYPE_INT_RGB);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}

public void paint(Graphics g) {


dessineLourd(monBuf.getGraphics()); // le dessin est effectue dans
le buffer
g.drawImage(monBuf,getInsets().left,getInsets().top,null); //
affichage du dessin pre-calcule
}

public void dessineLourd(Graphics g) {


Dimension d = getContentPane().getSize();
if (b)
g.setColor(Color.black);
else
g.setColor(Color.red);
b = !b;
for(int i=getInsets().left;i<d.width;i++)
for(int j=getInsets().top;j<d.height;j++)
g.drawLine(i,j,i,j);
}

public static void main(String[] args) {


BufferAntiScintillement mafenetre = new
BufferAntiScintillement(1000,600);
try {
for(int i=1;i<100;i++) {
Thread.sleep(500); // pause de 100 ms
mafenetre.repaint();
}
} catch(InterruptedException e) {};
}

13
2 Notions facultatives
2.1 Liste chaînée pré-conçue
2.1.1 Principe général
La classe LinkedList permet d’utiliser des listes chaînées sans avoir à re-
programmer les méthodes d’insertion, de suppression, etc. Chaque instance de
LinkedList est une liste chaînée pour laquelle chaque nœud est associé à une
instance d’une certaine classe. Dans le cas où cette classe correspond à Point,
l’instanciation s’écrit comme suit :
LinkedList<Point> maListe = new LinkedList<Point>();

L’instance maListe est alors une liste chaînée pour laquelle chaque nœud est
associé à une instance de Point.
Remarque. Dans le cas où l’on souhaite associer un type primitif (int, char, etc)
aux nœuds de la liste, on utilisera les objets correspondants aux types primitifs
comme Integer pour le type int :
LinkedList<Integer> maListe = new LinkedList<Integer>();

2.1.2 Exemple minimaliste

import java.awt.Point;
import java.util.LinkedList;

public class ListeChaine {

public static void main (String[] arg) {


// creation de la liste
LinkedList<Point> maListe = new LinkedList<Point>();

// remplissage en fin de liste


maListe.add(new Point(12,10));
maListe.add(new Point(0,1));
maListe.add(new Point(-8,5));

// acces direct a l’instance associe au noeud d’indice 1


Point p = maListe.get(1); // point de coordonnees (0,1)
System.out.println(p);

// supression de ce noeud
maListe.remove(1);

// nombre d’elements de la liste


int N = maListe.size();
System.out.println(N);
}
}

14
2.2 Obtenir les dimensions de l’écran
2.2.1 Principe général
Comme un programme Java peut être affiché sur des écrans de différentes
tailles, il peut être intéressant, lors de la création de la fenêtre de récupérer les
informations sur la taille de l’écran.
Pour être plus précis, il est possible de prendre en compte les dimensions des
bordures des fenêtres, de la barre des tâches et donc de distinguer la dimension
physique et la dimension utile.

2.2.2 Exemple minimaliste

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

public class Ecrans {

public static void main(String[] args) {


// Taille ecran physique
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice screen = env.getDefaultScreenDevice();
GraphicsConfiguration config = screen.getDefaultConfiguration();
System.out.println("Taille ecran physique : " +
config.getBounds());

// Taille zone utile


Rectangle bounds = env.getMaximumWindowBounds();
System.out.println("Taille ecran utile : " + bounds );

// Creation d’une fenetre vide et non visible


JFrame f = new JFrame("Frame Info"); // taille nulle pour l’instant
System.out.println("Fenetre taille : " + f.getSize() );

// Redimensionnement (en taille 400x200) et affichage de la fenetre


f.setSize(400, 200); // maintenant la taille est de 400x200
f.setVisible( true );
System.out.println("Fenetre taille physique: " + f.getSize() );
System.out.println("Positions bordures : " + f.getInsets() );
System.out.println("Fenetre taille utile : " +
f.getContentPane().getSize() );

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

15
2.3 Obtenir la taille d’un texte
2.3.1 Principe général
Le texte affiché sur une fenêtre a également une dimension que l’on peut
obtenir si nécessaire afin de placer des widgets correctement autour du texte.

2.3.2 Exemple minimaliste

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

public class TailleTexte extends JFrame {

public TailleTexte(int w, int h) {


setSize(w,h);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}

public void paint(Graphics g) {


Font font=g.getFont();
int hauteurTexte = getFontMetrics(font).getHeight();

g.setColor(Color.black);
g.drawString("La hauteur de ce texte est de "+hauteurTexte+"
pixels", 100,100);
}

public static void main(String[] args) {


TailleTexte Mafenetre = new TailleTexte(600,400);
}
}

16
2.4 Gérer un fichier texte
2.4.1 Principe général
Il est possible de lire des informations contenues dans un fichier, d’écrire des
informations dans un fichier ou d’effacer un fichier. Les exemples ci dessous per-
mettent de lire les informations contenues dans un fichier monFichierLire.txt
et d’écrire dans un fichier monFichierEcrire.txt.
Pour cela il existe différentes méthodes. Le choix a été fait ici de passer par
des tampons (appelés BufferedReader pour la lecture et BufferedWriter pour
l’écriture) pour éviter d’avoir à lire et/ou écrire caractère par caractère afin de
limiter le nombre d’accès en lecture et/ou écriture du fichier.
Il est important de ne pas oublier de fermer le fichier une fois les opérations
terminées sous peine de ne plus pouvoir l’utiliser.

2.4.2 Exemple minimaliste

import java.io.*;

public class GestionFichiers {

// Attributs
private String monFichier;

/** Constructeur
* @param leFichier : le nom du fichier
*/
public GestionFichiers(String leFichier) {
monFichier = leFichier;
}

/** Lecture d’un fichier


*/
public void lire() {
BufferedReader fichier = null;
try {
String ligne ;
fichier = new BufferedReader(new FileReader(monFichier));
while ((ligne = fichier.readLine()) != null) {
System.out.println(ligne);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fichier.close(); // Fermeture du fichier
System.out.println("Le fichier "+ monFichier +" a ete lu !");
} catch (Exception e) {
e.printStackTrace();
}
}
}

17
/** Ecriture dans le fichier
*/
public void ecrire(int nombre) {
BufferedWriter fichier = null;
try {
String ligne ;
fichier = new BufferedWriter(new FileWriter(monFichier));
fichier.write("Hello World");
fichier.newLine();
fichier.write("Voici du texte");
fichier.write(", et un nombre : " + nombre);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fichier.close(); // Fermeture du fichier
System.out.println("Le fichier "+ monFichier +" a ete ecrit
!");
} catch (Exception e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {


System.out.println("Test ecriture");
GestionFichiers testEcriture = new
GestionFichiers("monFichierEcrire.txt");
int unNombre=123;
testEcriture.ecrire(unNombre);
System.out.println("*-*-*-*-*-*");
System.out.println("Test lecture");
GestionFichiers testLecture = new
GestionFichiers("monFichierLire.txt");
testLecture.lire();

}
}

18
2.5 Méthode paint et JPanel
2.5.1 Principe général
Pour éviter d’avoir à redessiner la fenêtre entièrement à chaque fois, il est
possible de ne redessiner qu’une partie contenue dans un JPanel. Pour cela,
on peut créer notre propre JPanel et l’ajouter à notre fenêtre principale. La
méthode paint n’a besoin d’être redéfinie que dans ce nouveau JPanel.

2.5.2 Exemple minimaliste


Il faut définir son propre JPanel (ici dans un fichier nommé MonPaintJPanel.java) :
import java.awt.*;
import javax.swing.*;

public class MonPaintJPanel extends JPanel {

private Color myColor;

public MonPaintJPanel(Color c) {
myColor=c;
}

public void paint(Graphics g) {


// le fond
g.setColor( myColor);
g.fillRect(0,0,getWidth(),getHeight());
// Un rectangle
g.setColor( Color.cyan );
g.fillRect(10,10,50,40);
// une ellipse
g.setColor( Color.black );
g.fillOval(20,100,70,30);
}

et l’utiliser dans un programme gérant plusieurs JPanel :


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

public class PaintJPanelJFrame extends JFrame {

public PaintJPanelJFrame(int w, int h) {


setSize(w,h);
setLayout(null);

// Conteneur1
JPanel monConteneur1 = new JPanel();
monConteneur1.setBounds(50,10,500,80);
monConteneur1.setLayout(null);
monConteneur1.setBackground(Color.magenta);
JLabel monTexte = new JLabel("Voici mon 1er conteneur");

19
monTexte.setBounds(10,0,200,80);
JButton monBouton = new JButton("GO ?");
monBouton.setBounds(250,10,100,60);
monConteneur1.add(monTexte);
monConteneur1.add(monBouton);

// Conteneur2
MonPaintJPanel monConteneur2 = new MonPaintJPanel(Color.yellow);
monConteneur2.setBounds(20,110,560,240);
monConteneur2.setLayout(null);

// Conteneur principal
JPanel monConteneurPrincipal = new JPanel();
monConteneurPrincipal.setBounds(0,0,getWidth(),getHeight());
monConteneurPrincipal.setLayout(null);
monConteneurPrincipal.add(monConteneur1);
monConteneurPrincipal.add(monConteneur2);
setContentPane(monConteneurPrincipal);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}

public static void main(String[] args) {


PaintJPanelJFrame maFenetre = new PaintJPanelJFrame(600,400);
}
}

20
2.6 Mettre une image de fond et/ou superposer plusieurs
images/widgets
2.6.1 Principe général
Pour égayer votre IHM, il est possible d’insérer une image en arrière plan au
lieu d’une couleur unie appliquée avec la méthode setBackground. Le principe
est de créer un JLabel contenant l’image. On peut aussi superposer plusieurs
images et ajouter d’autres widgets. Attention l’ordre dans lequel ces widgets
sont ajoutés a une influence sur leur superposition. Ainsi les premiers ajoutés
seront au premier plan et les suivants sur un plan derrière. Le dernier élément
ajouté sera donc en arrière plan.

2.6.2 Exemple minimaliste


Voici un exemple permettant d’afficher plusieurs images superposées (le logo
INSA est sur l’image représentant le ciel) et des widgets (un bouton et une zone
de texte :
/**
* La fenetre principale pour gerer diffentes images superposees
*
*/

// Chargement des bibliothèques Swing et AWT


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

public class ImageFenetre extends JFrame{

public ImageFenetre(){
this.setTitle("mon IHM");
this.setSize(560,470);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

/**
* Mon panneau qui contient l’image
*/
JPanel panneauImage = new JPanel();
panneauImage.setBounds(20,20,500,400);
panneauImage.setLayout(null);

// On ajoute ensuite les différents composants


// Attention l’ordre d’ajout a une influence sur le rendu final
// Les premiers seront en premier plan et les derniers en
arrière plan
JButton monBouton = new JButton();
monBouton.setText("Bouton1");
monBouton.setBounds(15,10,120,50);
panneauImage.add(monBouton);

JTextField monTexte = new JTextField();


monTexte.setBounds(150,70,60,50);
panneauImage.add(monTexte);

21
// Mon JLabel qui contient une image
// Le fichier image doit se trouver dans le même dossier que les
fichiers java
JLabel monImage1 = new JLabel(new ImageIcon("insa_logo.png"));
monImage1.setBounds(340,20,140,55);
panneauImage.add(monImage1);

// Mon JLabel qui contient l’image qui sera au fond


// Le fichier image doit se trouver dans le même dossier que les
fichiers java
JLabel monImage2 = new JLabel(new ImageIcon("sky.jpg"));
monImage2.setBounds(0,0,panneauImage.getWidth(),panneauImage.getHeight());
panneauImage.add(monImage2);

/**
* Mon panneau Global
*/
JPanel panneauGlobal = new JPanel();
panneauGlobal.setBounds(0,0,400,400);
panneauGlobal.setLayout(null);
panneauGlobal.setBackground(Color.yellow);
panneauGlobal.add(panneauImage);

// On applique ce panneau global sur le JFrame


add(panneauGlobal);

// Pour rendre la fenêtre visible


this.setVisible(true);

/**
* La methode main est placee ici pour des raisons de simplicite
* mais elle devrait se trouver dans une autre classe
*/
public static void main(String[] args){

// Création de la fenêtre pour l’IHM


ImageFenetre maFrame = new ImageFenetre();
}
}

22
2.7 Gérer un groupe de JRadioButton
2.7.1 Principe général
Pour permettre de faciliter l’interaction avec l’utilisateur, il est possible de
lui proposer un groupe de JRadioButton. Ce dernier permet à l’utilisateur de
choisir une et unique option parmi celles proposées. Ainsi lorsque l’utilisateur
fait un choix en cliquant sur une option, les autres sont désélectionnées auto-
matiquement afin de ne pouvoir en choisir qu’une. Pour cela, il faut créer des
JRadioButton et les regrouper dans un ButtonGroup. Il faut penser aussi à ajouter
un écouteur à ces JRadioButton afin de récupérer l’action de l’utilisateur.

2.7.2 Exemple minimaliste


Voici un exemple proposant 3 choix à l’utilisateur et d’afficher son choix dans
une zone de texte :
/**
* La fenetre principale pour gerer des radio boutons
* La selection de l’un deselectionne les autres
* et affiche le choix dans un JTextField
*
*/

// Chargement des bibliothèques Swing et AWT


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

public class RadioBoutonFenetre extends JFrame implements ActionListener


{

// Les attributs (widgets utilisés en dehors du constructeur)


private JRadioButton monRadio1;
private JRadioButton monRadio2;
private JRadioButton monRadio3;
private JTextField monTexte;

public RadioBoutonFenetre(){
this.setTitle("mon IHM");
this.setSize(560,470);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

/**
* Mon panneau qui contient les radio boutons
*/
JPanel panneauRadio = new JPanel();
panneauRadio.setBounds(20,20,500,400);
panneauRadio.setLayout(null);
panneauRadio.setBackground(Color.blue);

// On ajoute ensuite les différents RadioBoutons


monRadio1 = new JRadioButton("Choix 1");
monRadio1.setBounds(15,10,120,50);

23
monRadio1.addActionListener(this);
panneauRadio.add(monRadio1);

monRadio2 = new JRadioButton("Choix 2");


monRadio2.setBounds(15,70,120,50);
monRadio2.addActionListener(this);
panneauRadio.add(monRadio2);

monRadio3 = new JRadioButton("Choix 3");


monRadio3.setBounds(15,130,120,50);
monRadio3.addActionListener(this);
panneauRadio.add(monRadio3);

// On les regroupe pour que la sélection de l’un désélectionne


les autres
ButtonGroup group = new ButtonGroup();
group.add(monRadio1);
group.add(monRadio2);
group.add(monRadio3);

monTexte = new JTextField();


monTexte.setBounds(150,70,60,50);
panneauRadio.add(monTexte);

/**
* Mon panneau Global
*/
JPanel panneauGlobal = new JPanel();
panneauGlobal.setBounds(0,0,400,400);
panneauGlobal.setLayout(null);
panneauGlobal.setBackground(Color.yellow);
panneauGlobal.add(panneauRadio);

// On applique ce panneau global sur le JFrame


add(panneauGlobal);

// Pour rendre la fenêtre visible


this.setVisible(true);

/**
* La methode appelee lorsqu’on clique sur un radiobouton
*/
public void actionPerformed(ActionEvent e){
if (e.getSource()==monRadio1){
monTexte.setText(monRadio1.getText());
}
else if (e.getSource()==monRadio2){
monTexte.setText(monRadio2.getText());
}
else if (e.getSource()==monRadio3){
monTexte.setText(monRadio3.getText());
}

24
}

/**
* La methode main est placee ici pour des raisons de simplicite
* mais elle devrait se trouver dans une autre classe
*/
public static void main(String[] args){

// Création de la fenêtre pour l’IHM


RadioBoutonFenetre maFrame = new RadioBoutonFenetre();
}
}

25
2.8 Tracé d’une fonction
2.8.1 Principe général
L’objectif ici est de tracer la suite de fonctions mathématiques suivante dans
un intervalle donné :
x

fn (x) = sin (2n + 1) ∗ π ∗ 20
La difficulté réside ici dans le fait que le repère “mathématique” classique-
ment utilisé a une origine au centre, l’axe des abscisses de la gauche vers la
droite et l’axe des ordonnées du bas vers le haut. Or le repère “graphique” sous
java est inversé pour l’axe des ordonnées et l’origine est en haut à gauche de la
fenêtre. Il faut donc faire une conversion pour passer de l’un à l’autre.

2.8.2 Exemple minimaliste

/**
* Classe permetttant de dessiner entre xA et xB
* la suite de fonction fn(x)=sin((2n+1)*PI*x/20)
*/

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

public class Courbe extends JFrame {

private double xA;


private double xB;

/**
* Constructeur
* @param a et b l’intervalle d’etude de la fonction
*/
public Courbe(int a, int b) {
xA=a;
xB=b;
setTitle("Courbe fn(x)=sin((2n+1)*PI*x/20) entre "+xA+" et "+xB);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800,200);
setVisible(true);
}

/**
* Definition de la fonction mathematique
* @param n le nombre de courbes a dessiner
* @param x la valeur pour laquelle il faut calculer la fonction
* @return f_n(x)
* Les coordonnees sont calculees dans le repere "mathematique"
*/
private double fn(int n, double x) {
return Math.sin((2*n+1)*(Math.PI) * x/20);
}

/**

26
* Pour convertir les coordonnees par rapport a notre fenetre
graphique
* @param x la valeur en abscisse a mettre entre 0 et la largeur l
* @param y la valeur en ordonnee a mettre entr 0 et la hauteur h
* @return les coordonnees du point a tracer sur le graphique
*/
private Point ToScreen(double x, double y) {
// calcul la hauteur et largeur de la surface visible de la fenetre
int h=getSize().height-getInsets().top-getInsets().bottom;
int l=getSize().width-getInsets().left-getInsets().right;
// Conversion entre le repere "mathematique" et le repere
"graphique"
int xE=(int)((x-xA)/(xB-xA)*l);
int yE=(int)((y+1)/2*h);
return new Point(xE+getInsets().left,yE+getInsets().top);
}

/**
* La methode paint pour dessiner les fonctions
*/
public void paint(Graphics g) {
Color[] tabCouleur =
{Color.black,Color.gray,Color.blue,Color.cyan,Color.green,
Color.magenta,Color.orange,Color.pink,Color.red,Color.yellow};
Point a,b;
double x,y;
// Mettre le fond blanc
g.setColor(Color.white);
g.fillRect(0,0,getSize().width,getSize().height);
// Dessiner le repere centre
g.setColor(Color.black);
a=ToScreen(0,+1); b=ToScreen(0,-1); g.drawLine(a.x,a.y,b.x,b.y);
a=ToScreen(xA,0); b=ToScreen(xB,0); g.drawLine(a.x,a.y,b.x,b.y);
// Tracer 9 courbes fn(x)
for (int n=1; n<10; n++) {
g.setColor(tabCouleur[n]);
x=xA; y=fn(n,xA); a=ToScreen(x,y);
// Trace un courbe fn(x) avec x de xA à xB
while (x<=xB)
{
x+=0.05; y=fn(n,x);
b=ToScreen(x,y); g.drawLine(a.x,a.y,b.x,b.y);
a=b; // on sauve le point precedent
}
}
}

public static void main(String[] args) {


Courbe maFenetre = new Courbe(-5,5);
}

27
}

28

Vous aimerez peut-être aussi