Une image qui défile                  

Une image qui défile

     

alt : l'applet n'est pas visible par votre navigateur ; pour voir l'application, vous devez télécharger le code, le compiler et l'exécuter

Nous proposons un exemple qui fait défiler une image. L'image défile de droite à gauche ; quand elle a disparu, elle reparaît à droite. Nous avons choisi de construire une image constituée d'une image chargée à partir d'un fichier (représentant la Terre) et d'une chaîne de caractères et de faire défiler l'image obtenue. L'essentiel du travail consiste à prendre quelques mesures. Nous utilisons encore un timer. Par ailleurs, dans la méthode construireImage, on utilise la méthode createImage définie dans la classe Component ; cette méthode ne peut être utilisée que lorsque le composant à partir duquel on crée l'image est disponible ; c'est pour cette raison qu'on invoque la méthode construireImage dans paintComponent.

À la fin de la méthode construireImage, l'image est écrite dans un fichier.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

class IHMDefile extends JPanel implements ActionListener {
	
	private static final long serialVersionUID = 1L;
	private Timer timer;
	private int pas = 10;
	private int x;
	private Image image;
	private int largeurImage;

	IHMDefile() {
		setPreferredSize(new Dimension(400, 150));
		setBackground(Color.YELLOW);
		timer = new Timer(100, this);
		timer.start() ;

}

	void construireImage() {
		Image terre;
		String chaine = "Java est un beau langage et son apprentissage est un vrai plaisir";
	
		try {
			terre = javax.imageio.ImageIO.read (new File("world.gif"));
			int largeurMonde = terre.getWidth(this);
			int hauteurMonde = terre.getHeight(this);
			Font fonte = new Font("TimesRoman",Font.PLAIN, 25);
			FontMetrics mesure = getFontMetrics(fonte);
			int hauteurChaine = mesure.getHeight();
			int largeurChaine = mesure.stringWidth(chaine);

			largeurImage = largeurChaine + largeurMonde + 10;
			int hauteurImage = (hauteurMonde > hauteurChaine ?hauteurMonde : hauteurChaine);
			int yChaine = (hauteurImage + mesure.getAscent())/2;

			image = createImage(largeurImage, hauteurImage);

			Graphics g = image.getGraphics();
			g.setColor(Color.YELLOW);
			g.fillRect(0, 0, largeurImage, hauteurImage);
			g.drawImage(terre, 0, (hauteurImage - hauteurMonde)/2, this);
			g.setFont(fonte);
			g.setColor(Color.RED);
			g.drawString(chaine, largeurMonde + 10, yChaine);
			g.dispose();
			javax.imageio.ImageIO.write((java.awt.image.BufferedImage)image, "jpeg", new java.io.File("defile.jpg"));
		}
		catch (IOException exc) {
			exc.printStackTrace();
		}
	}

	public void actionPerformed(ActionEvent e) {
		x = x - pas;
	
		// si l'image est sortie sur la droite, on la fait repartir de la gauche
		if (x < -largeurImage)  x = getWidth();
		repaint();
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
	
		if (image == null) construireImage();
		g.drawImage(image, x, 40, this);
	}
}

class Defile  {
	public static void main(String[] arg) {
		JFrame fenetre = new JFrame();
		fenetre.setContentPane(new IHMDefile());
		fenetre.setLocation(100, 100);
		fenetre.pack();
		fenetre.setVisible(true);	
		fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}

setBackground(Color.YELLOW); : on a choisi de colorier en jaune le fond du composant dans lequel on dessine l'image, et on fera le même choix pour le fond de l'image qui défile ; on ne verra donc pas les limites de l'image qui défile. terre.getWidth(this); : l'argument doit être un ImageObserver, ce qui est le cas ici car la classe Component implémente cette interface. La méthode getWidth renvoie -1 si la largeur de l'image n'est pas encore connue.
image = createImage(largeurImage, hauteurImage); : crée une image ayant les dimensions indiquées ; cette image pourra être tracée dans un composant graphique par la méthode drawImage. La méthode createImage de la classe java.awt.Component renvoie null tant que la construction du composant concerné n'est pas achevée.
Graphics g = image.getGraphics(); : on récupère le contexte graphique de l'image créée. On peut alors effectuer des tracés dans l'image comme on le fait dans un composant.
g.fillRect(0, 0, largeurImage, hauteurImage); : l'instruction précédente du programme a donné la couleur jaune à g ; on remplit la surface de l'image d'un rectangle plein jaune pour que le fond de l'image soit jaune.
g.dispose(); : il ne faut pas oublier de libérer le contexte graphique consommateur de beaucoup de ressources.
javax.imageio.ImageIO.write((java.awt.image.BufferedImage)image, "jpeg", new java.io.File("defile.jpg")); : cette instruction n'est pas utile pour npotre application et n'est là que pour faure un exemple ; elle écrit l'image avec le format jpeg dans fichier defile.jpg. Cette méthode write attend en premier argument un BufferedReader, ce qui explique la conversion de type ; cette conversion fonctionne car la méthode createImage utilisée pour construire image indique dans son prototype qu'elle renvoie une instance de Image mais l'instance renvoyée est une instance de BufferedImage, ce qui est compatible avec le fait que la classe BuferedImage étend la classe Image.

© Irène Charon, Télecom ParisTech, 2011