badr benmammar bbm@badr-benmammar.com thread et swing

Download Badr Benmammar bbm@badr-benmammar.com Thread et Swing

Post on 04-Apr-2015

114 views

Category:

Documents

9 download

Embed Size (px)

TRANSCRIPT

  • Page 1
  • Badr Benmammar bbm@badr-benmammar.com Thread et Swing
  • Page 2
  • Plan Tche longue dans un une interface utilisateur graphique (GUI ) Deadlock dinitialisation de GUI Pattern de cration dun GUI Tche priodique dans un GUI Rgle dunicit du thread GUI Class SwingWorker : tche longue proprement Tche longue avec interruption possible Interaction avec levent-dispatcher
  • Page 3
  • Tche longue dans un GUI Problme : excuter une tche relativement longue dans le cadre dune (GUI) interface graphique pour lutilisateur. La tche dure quelques secondes voire des minutes. Linterface doit pouvoir encore ragir aux actions de lutilisateur. La longue tche excuter est simule par des "sleep" dans sa mthode execute(). Elle doit indiquer son avancement dans une barre de progression, mais aussi dans la console.
  • Page 4
  • Tche longue dans un GUI import java.awt.*; import java.awt.event.*; import javax.swing.*; public class GUIetTacheLongue1 extends JFrame { JProgressBar barreProgression; public GUIetTacheLongue1() { super("GUIetTacheLongue1"); Container contentPane = getContentPane(); barreProgression = new JProgressBar(); JButton bouton= new JButton("Demarrer la tache longue"); contentPane.add(bouton,BorderLayout.NORTH); contentPane.add(barreProgression,BorderLayout.SOUTH); bouton.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent e) { LongueTache1 tache = new LongueTache1(); tache.execute(barreProgression); } ); pack(); setVisible(true); } public static void main(String[] args) { new GUIetTacheLongue1(); } } class LongueTache1 { public void execute (JProgressBar barreProgression) { barreProgression.setMinimum(0); barreProgression.setMaximum(99); barreProgression.setValue(0); for (int i = 0; i < 100; i++ ) { barreProgression.setValue(i); System.out.print("."); try {Thread.sleep(100);} catch (InterruptedException e) {} } System.out.println("") ; } La tche longue Classe interne anonyme pour installer un couteur correspond au composant bouton
  • Page 5
  • Tche longue dans un GUI................................................................................................................. $ Remarque : Arrtez avec car la fermeture de la fentre et larrt de lappli ne sont pas prvus pour allger le code. La "longue tche", visiblement, fonctionne car elle se trace dans la console. Mais la barre de progression Swing nest mise jour qu la fin ! Excution:
  • Page 6
  • Multitche avec un thread import java.awt.*; import java.awt.event.*; import javax.swing.*; public class GUIetTacheLongue2 extends JFrame { JProgressBar barreProgression; public GUIetTacheLongue2() { super("GUIetTacheLongue2"); Container contentPane = getContentPane(); barreProgression = new JProgressBar(); JButton bouton= new JButton("Demarrer la tache longue"); contentPane.add(bouton,BorderLayout.NORTH); contentPane.add(barreProgression,BorderLayout.SOUTH); bouton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Thread t = new Thread() { public void run() { LongueTache2 tache = new LongueTache2(); tache.execute(barreProgression); } }; t.start(); } } ); pack(); setVisible(true);} //fin constructeur public static void main(String[] args) { new GUIetTacheLongue2(); } } // fin de la classe GUIetTacheLongue2 class LongueTache2 { public void execute (JProgressBar barreProgression) { barreProgression.setMinimum(0); barreProgression.setMaximum(99); barreProgression.setValue(0); for(int i = 0; i < 100; i++ ) { barreProgression.setValue(i); System.out.print("."); try {Thread.sleep(100); } catch (InterruptedException e) {} } System.out.println("") ; } Une nouvelle classe interne anonyme qui est imbrique dans la prcdente classe interne anonyme afin dimplmenter le thread.
  • Page 7
  • Multitche avec un thread Pour que la longue tche et le Gui soient excuts "en mme temps", on lance un thread de plus pour la longue tche. Excution :................................................................................................................. $ Le thread "longue tche", visiblement, fonctionne car il se trace dans la console et la barre de progression Swing est mise jour progressivement.
  • Page 8 thread name = " + Thread.currentThread().getName()); JFrame frame = new JFrame("ThreadSwing"); JButton bouton = new JButton("Afficher"); frame.getContentPane().add(bouton); bouton.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent e) { System.out.println ("actionPerformed -----> thread name = " +Thread.currentThread().getName()); } }); frame.pack(); frame.setVisible(true); } Excution : main -----> thread name = main actionPerformed -----> thread name = AWT-EventQueue-0">
  • Utilitaire pour tracer les threads import java.awt.*; import java.awt.event.*; import javax.swing.*; class ThreadSwing { public static void main(String args[]) { System.out.println("main -----> thread name = " + Thread.currentThread().getName()); JFrame frame = new JFrame("ThreadSwing"); JButton bouton = new JButton("Afficher"); frame.getContentPane().add(bouton); bouton.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent e) { System.out.println ("actionPerformed -----> thread name = " +Thread.currentThread().getName()); } }); frame.pack(); frame.setVisible(true); } Excution : main -----> thread name = main actionPerformed -----> thread name = AWT-EventQueue-0
  • Page 9
  • Utilitaire pour tracer les threads Ce code sexcute sur 2 threads : main pour pack, setVisible (raliser les composants). AWT-EventQueue-0 pour laction (les vnements). Swing (et AWT) dispose dun thread spcifique pour traiter les vnements : levent dispatcher : AWT-EventQueue-0 qui excute les "handlers"/mthodes associes aux vnements. Une file permet de mettre en attente ordonne les vnements qui arrivent.
  • Page 10
  • Deadlock dinitialisation de GUI import . public class SwingThreadDeadlock extends JPanel implement ComponentListener{ private static JFrame frame; private JTextArea trace; public SwingThreadDeadlock() { . } void componentHidden(ComponentEvent e) {} // invoquer quand le composant devient invisible Void componentMoved(ComponentEvent e) {} // invoquer quand le composant change de position Void componentResized(ComponentEvent e) {} // invoquer quand le composant change de taille void componentShown(ComponentEvent e) {} // invoquer quand le composant devient visible private static void createAndShowGUI() { frame.pack(); frame.setVisible(true); } public static void main(String[] args) { createAndShowGUI(); } Cest un couteur de composant
  • Page 11
  • Deadlock dinitialisation de GUI private static void createAndShowGUI() { frame.pack(); frame.setVisible(true); } public static void main(String[] args) { createAndShowGUI(); } public void componentResized (ComponentEvent e) { Afficher un texte dans un composant qui appartient a la frame. (trace de type JTextAera). } pack provoque des events componentResized. La mthode componentResized agit sur le composant JTextAera qui nest pas encore visible. Do linterblocage (deadlock). Solution : il faut sassurer que tous les composants sont visibles avant de lancer les vnements. AWT-EventQueue-0
  • Page 12
  • Pattern de cration dun GUI public static void main(String[] args) { SwingUtilities.invokeLater (new Runnable() { public void run() { createAndShowGUI(); } }); } invokeLater (Runnable tache) est une mthode static de la classe SwingUtilities : Fera excuter la mthode createAndshowGUI dans le thread event-dispatcher (AWT-EventQueue-0). Cette demande est ajoute dans la file des vnements en attente de traitement, comme il ny a pas encore de composant, ce sera le premier traitement et ceci vite le deadlock. Cette mthode retourne immdiatement dans le thread appelant.
  • Page 13
  • Tche priodique dans un GUI Tche effectuer : dclencher un compte rebours de 6 secondes. Toutes les secondes, il faut changer le label affich et, la fin, afficher fini. La tche priodique est excute par un Timer Swing. Le Timer Swing se trouve dans javax.swing. Diffrent de Timer qui est dans java.util. Le constructeur Timer (period, listener) instancie un Timer de la priode dsire avec un listener dsign. Aux instants ad-hoc, le timer enverra un vnement ActionEvent au listener. La mthode setInitialDelay (dlai) dfinit un dlai initial avant ltablissement des priodes. La mthode setCoalesce (boolen) dfinit la politique du timer en cas dencombrement : si true, et sil y a plusieurs events gnrer (du fait dun retard), alors le timer nenvoie quun unique event.
  • Page 14
  • import java.awt.*; import java.awt.event.*; import javax.swing.*; public class GUIetTachePeriodique8 extends JFrame implements ActionListener { private JLabel etatTachePeriodique; private JButton boutonGo; private int compteur; private Timer timer; public GUIetTachePeriodique8() { super("GUIetTachePeriodique8"); Container contentPane = getContentPane(); boutonGo = new JButton("Demarrer"); contentPane.add(boutonGo,BorderLayout.NORTH); etatTachePeriodique = new JLabel ("pas de tache periodique"); contentPane.add(etatTachePeriodique,BorderLayout.CENTER); boutonGo.addActionListener(this); pack(); setVisible(true); } Tche priodique dans un GUI public void actionPerformed(ActionEvent e) { if (e.getActionCommand() != null) { boutonGo.setEnabled(false); compteur = 6; etatTachePeriodique.setText("reste "+ compteur +" secondes"); timer = new Timer(1000, this); /* chaque seconde, le timer envoie un vnement son couteur */ timer.setInitialDelay(1000); // dlai initial timer.setCoalesce(true); /* true, sil y a plusieurs events gnrer