Dessiner un disque

     

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

L'objectif principal ici est d'illustrer comment démarrer un thread, ou bien le suspendre, ou bien le faire reprendre où il en était avant d'avoir été suspendu, ou bien l'arrêter définitivement. On aurait pu utiliser les méthodes suspend (suspension d'une thread permettant une reprise éventuelle au point d'arrêt), resume (reprise d'une thread arrêtée par la méthode suspend) et stop (arrêt définitif du thread) de la classe Thread mais ces méthodes sont "deprecated" depuis la version 1.2 du langage.

Vous pourrez remarquer l'utilisation de la méthode isAlive() qui permet de savoir si un thread est ou non en cours d'exécution. La méthode retourne la valeur true si l'exécution de la méthode run est commencée et non terminée ; si le thread a été interrompue par la méthode stop, isAlive retourne false.

On aurait pu effectuer le même travail en utilisant un "timer", comme nous le verrons dans le chapitre sur les animations. Ce serait plus simple, mais n'utiliserait pas directement les threads...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;

class ThreadSimple extends Thread
{
  int r=10;
  int debut;
  boolean continuer;
  boolean finir;
  JPanel panneauDisque;

  ThreadSimple(int debut,  JPanel panneauDisque)
  {
    this.debut = debut;
    this.panneauDisque = panneauDisque;
  }

  void suspendre()
    {
      continuer = false;
    }

  synchronized void reprendre()
    {
        continuer = true;
	notify();
    }

  synchronized void stopper()
    {
        finir = true;
	notify();
    }
  
  public void run()
  {
    Graphics g = fenetre.getGraphics();

    continuer = true;
    finir = false;
    for (int i = 0; i < 30; i++)
      {
	try
	  {
            sleep(200); 
	    synchronized(this)
	      {	   
		while (!continuer && !finir) wait();
	      }
	  }
	catch (InterruptedException exc) {}
	if (finir) break;
	g.setColor(new Color((debut+528424*i)%Integer.MAX_VALUE));
	g.drawOval(200-r, 150-r,2*r,2*r);
	r += 2;
      }
  }
}

class PanneauThreadSimple extends JPanel implements ActionListener
{
  ThreadSimple thread = null;
  Random alea; 
  JButton tracer = new JButton("tracer");
  JButton pauser = new JButton("pauser");
  JButton stopper = new JButton("stopper");
  JButton effacer = new JButton("effacer");
  JPanel panneauDisque = new JPanel();

  PanneauThreadSimple()
    {
      setLayout(new BorderLayout(5, 5));
      JPanel panneauBouton = new JPanel();
      panneauDisque.setPreferredSize(new Dimension(400,300));
      tracer.addActionListener(this);
      pauser.addActionListener(this);
      stopper.addActionListener(this);
      effacer.addActionListener(this);
      panneauBouton.add(tracer);
      panneauBouton.add(pauser);
      panneauBouton.add(stopper);
      panneauBouton.add(effacer);
      add(panneauBouton, BorderLayout.NORTH);
      add(panneauDisque, BorderLayout.CENTER);
      alea = new Random();
    }
  
  public void actionPerformed(ActionEvent evt)
    {
      Object source = evt.getSource();

      if (source == tracer)   
	{
	  int debut= (int)Math.abs(alea.nextLong());
	  
	  if ((thread == null)||(!thread.isAlive()))  
	    {
	      thread = new ThreadSimple(debut, this);
	      thread.start();
	    }
	  else thread.reprendre();
	}

      else if ((source == pauser) && (thread != null)) 
                            thread.suspendre(); 

      else if (source == stopper)  
	{
	  if (thread != null) thread.stopper();
	  thread = null;
	}

      else if (source == effacer) repaint();
    }
  
}

public static void main(String[] argv)
  {
    JFrame f = new JFrame();
    f.setContentPane(new PanneauThreadSimple());
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.pack();
    f.setVisible(true);
  }
}


Vous pouvez accéder :

  • au code de l'application que vous voyez aussi ci-dessus
  • au code de l'applet.
    sleep(200) : on demande ainsi à une thread d'attendre le temps indiqué en millisecondes dans l'argument. C'est très utile dans une animation pour ralentir le mouvement.
    Random alea : la classe java.util.Random permet d'avoir un générateur pseudo-aléatoire d'int, de long, de float, de double.
    thread.isAlive() : la méthode isAlive retourne la valeur true si l'exécution de la méthode run est commencée et non terminée ; si la thread a été interrompue par la méthode stop, isAlive retourne false, mais elle retourne true si la thread est supendue.
    alea = new Random(); : on construit ainsi un générateur aléatoire qui sera initialisé (presque sûrement) à une nouvelle valeur à chaque appel.

    © Irène Charon, Télécom ParisTech 2011