import javax.swing.*;import javax.swing.border.BevelBorder;import java.awt.*;public class WaitingBar extends JComponent implements Runnable{ //pour tester... TODO: enlever ce main public static void main(String[] args) throws InterruptedException { JFrame form = new JFrame(); WaitingBar barre = new WaitingBar( 240, 24, Color.BLACK, Color.GREEN, 9); form.setBackground(Color.BLACK); form.getContentPane().setBackground(Color.BLACK); form.getContentPane().setLayout(null); barre.setLocation(new Point(30,30)); form.getContentPane().add(barre); form.setSize(300,300); form.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); form.setVisible(true); barre.startAnim(); Thread.sleep(3000); barre.stopAnim(); Thread.sleep(3000); barre.startAnim(); Thread.sleep(3000); barre.killAnim(); Thread.sleep(3000); barre.rezAnim(); } private static final long serialVersionUID = 1L; private boolean isRunning, isDead; private int cptr, nbBarres, fps; private Color[] tabCouleurs; public WaitingBar() { this(Color.WHITE, Color.BLACK); } public WaitingBar(int width, int height, Color couleurDebut, Color couleurFin, int nbBarres) { super(); //initialisation des propriétés this.nbBarres = nbBarres; this.cptr = 100; this.isRunning = false; this.isDead = false; this.tabCouleurs = new Color[19]; this.fps = 25; //initialisation du tableau de couleurs this.setCouleurs(couleurDebut, couleurFin); //initialisations des propriétés de JComponent this.setSize(width, height); this.setOpaque(true); this.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, SystemColor.controlDkShadow, SystemColor.controlHighlight)); //initialisation du thread qui gère l'animation. new Thread(this).start(); } public WaitingBar(Color couleurDebut, Color couleurFin) { this(120,32,couleurDebut,couleurFin,7); } /** * Définit les 2 couleurs entre lesquelles l'animation oscille. * * @param couleurDebut Couleur de début pour l'animation. * @param couleurFin Couleur de fin pour l'animation. */ public void setCouleurs(Color couleurDebut, Color couleurFin) { double diffR, diffG, diffB; //calcul de la difference pour chaque valeur RGB pour les deux couleurs diffR = ((double)couleurDebut.getRed() - (double)couleurFin.getRed()) / 9; diffG = ((double)couleurDebut.getGreen() - (double)couleurFin.getGreen()) / 9; diffB = ((double)couleurDebut.getBlue() - (double)couleurFin.getBlue()) / 9; //définition des valeurs limites du tableau; tabCouleurs[0] = tabCouleurs[18] = couleurDebut; //définition des autres valeurs ( 1 -> 17 ) for(int i = 1; i < 10; i++) { tabCouleurs[i] = new Color( (int)(couleurDebut.getRed() - diffR * i), (int)(couleurDebut.getGreen() - diffG * i), (int)(couleurDebut.getBlue() - diffB * i)); //[1] == [17], [2] == [16]... donc [18 - i] = [i]; tabCouleurs[18 - i] = tabCouleurs[i]; } } /** * Retourne la couleur de début de l'animation * * @return Couleur de début. * @see getCouleurFin(), setCouleurs(Color couleurDebut, Color couleurFin) */ public Color getCouleurDebut() { return tabCouleurs[0]; } /** * Retourne la couleur de fin de l'animation * * @return Couleur de fin. * @see getCouleurDebut(), setCouleurs(Color couleurDebut, Color couleurFin) */ public Color getCouleurFin() { return tabCouleurs[9]; } /** * Démarre l'animation de la WaitingBar. * @see stopAnim(), rezAnim() */ public void startAnim() { isRunning = true; } /** * Arrête l'animation de la WaitingBar. * @see startAnim(), killAnim() */ public void stopAnim() { isRunning = false; repaint(); } /** * Arrête l'animation de la WaitingBar et finit le thread * qui s'occupe de l'animation... Il faut appeler rezAnim() pour * repartir l'animation lorsqu'elle est arrêté avec killAnim(). *@see rezAnim(), stopAnim() */ public void killAnim() { stopAnim(); isDead = true; } /** * Crée un nouveau thread pour repartir l'animation si le thread * n'existe plus. Dans le cas ou l'animation est seulement arrêtée, * l'appel de cette fonction relance l'animation sans créer de nouveau * Thread. Il est préférable d'appeler startAnim() si on veut seulement * repartir l'animation. * *@see killAnim(), startAnim() */ public void rezAnim() { if(isDead) { startAnim(); isDead = false; new Thread(this).start(); } } /** * Retourne une couleur de bordure appropriée pour les couleurs * d'animation courantes * * @return Couleur de bordure de chaque rectangle. */ private Color getBorderColor() { Color c1,c2; c1 = getCouleurDebut(); c2 = getCouleurFin(); //retourne blanc si la moyenne des deux couleurs est plus //foncé que le gris milieu, et noir si elle est plus pale. if(c1.getBlue() + c1.getRed() + c1.getGreen() + c2.getBlue() + c2.getRed() + c2.getGreen() <= 255 * 6 / 2) { return Color.WHITE; } return Color.BLACK; } /** * Retourne l'état de l'animation. * @return Retourne TRUE si l'animation de la WaitingBar est en train de jouer * ou FALSE si elle est stoppée. */ public boolean isRunning() { return isRunning; } /** * JComponent.update(Graphics g) * @see paint(Graphics g) */ public void update(Graphics g) { paint(g); } /** * JComponent.paint(Graphics g) */ public void paint(Graphics g) { //variables pour le double-buffering Image bufferImg = createImage(getWidth(), getHeight()); Graphics2D bufferG = (Graphics2D) bufferImg.getGraphics(); //paint du background avec un effet dégradé sur les couleurs //systemes bufferG.setPaint(new GradientPaint( 0,0, SystemColor.control, getHeight() / 20, getHeight() / 2, SystemColor.controlDkShadow, true)); bufferG.fillRect(0,0,getWidth(),getHeight()); //sommes des delta en pourcentage pour les espacements en X et en Y double sommeDeltasYPct = 0.20; double sommeDeltasXPct = 0.20; //valeur absolue des delta X et Y double deltaY = Math.round(getHeight() * sommeDeltasYPct / 2); double deltaX = Math.round(getWidth() * sommeDeltasXPct / (nbBarres + 1)); //ajustement si nécessaire if(deltaY < 1) deltaY = 1; if(deltaX < 1) deltaX = 1; //calcul de la taille de chaque rectangle double rectWidth = Math.round((getWidth() - (deltaX * (nbBarres + 1))) / nbBarres); double rectHeight = Math.round(getHeight() - (deltaY * 2)); //dessin des rectangles for(int i = 0; i < nbBarres; i++) { if(isRunning()) //définition de la couleur avec le tableau de couleur selon i pour //avoir un effet de transistion. bufferG.setColor(tabCouleurs[ (int)(cptr - i * 2) % tabCouleurs.length ]); else //si l'animation est stoppée, tous les rectangles ont la meme couleur bufferG.setColor(getCouleurDebut()); bufferG.fillRect( (int)(deltaX + (i * (deltaX + rectWidth))), (int)deltaY, (int)rectWidth, (int)rectHeight ); //dessin de la bordure bufferG.setColor(getBorderColor()); bufferG.drawRect( (int)(deltaX + (i * (deltaX + rectWidth))), (int)deltaY, (int)rectWidth, (int)rectHeight ); } //dessin du buffer sur l'écran g.drawImage(bufferImg, 0, 0, null); //on dessine la bordure du JComponent paintBorder(g); } /** * Runnable.run() */ public void run() { while(true && !isDead) { //on sauve les millisecondes avant l'affichage long beforeTime = System.currentTimeMillis(); if(isRunning()) { repaint(); cptr++; } //on calcule le temps écoulé pour l'affichage long elapsedTime = System.currentTimeMillis() - beforeTime; try { //on calcule le temps à dormier selon le FPS et le temps écoulé long timeToSleep = 1000 / fps - elapsedTime; if(timeToSleep > 0) Thread.sleep(timeToSleep); } catch (InterruptedException e) {} } }}