1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
| class TestFrame extends JFrame {
private final DefaultListModel model = new DefaultListModel();
private final JList list = new JList(model);
private final JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
private final JButton button = new JButton("Go");
public TestFrame() {
super("Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setLocationRelativeTo(null);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
buttonPerformed();
}
});
panel.add(button);
ImageIcon icon = null;
try {
icon = new ImageIcon(new URL("http://adiguba.developpez.com/blog/duke.running.gif"));
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
getContentPane().add(new JScrollPane(list));
getContentPane().add(panel, BorderLayout.SOUTH);
getContentPane().add(new JLabel(icon), BorderLayout.EAST);
}
private void buttonPerformed() {
// Cette méthode est appelée par actionPerformed()
// On est donc dans l'EDT on peut mettre à jour notre interface :
final JProgressBar progress = new JProgressBar(0, 100);
progress.setStringPainted(true);
// On grise le bouton :
button.setEnabled(false);
// Et on ajoute une JProgressBar :
panel.add(progress);
panel.revalidate();
// On crée notre SwingWorker qui va effectuer le traitement :
SwingWorker<Long, Double> worker = new SwingWorker<Long, Double>() {
/**
* La méthode doInBackground() permet d'effectuer
* les traitements lourds.
* Cette méthode est toujours exécutée dans un thread séparé.
* On ne doit pas y modifier l'interface graphique
*/
@Override
protected Long doInBackground() throws Exception {
long time = System.currentTimeMillis();
for (int i=0; i<10; i++) {
// setProgress() permet d'indiquer l'état du SwingWorker,
// et de le coupler avec une JProgressBar (voir plus loin)
setProgress(i*10);
// On simule un traitement 'lent' en endormant le thread :
Thread.sleep((int)(Math.random()*1000));
// On génère une valeur aléatoire :
Double value = Math.random();
// On utilise publish() pour publier la valeur
// (voir la méthode process() ci-dessous)
publish(value);
}
setProgress(100);
time = System.currentTimeMillis() - time;
// On peut eventuellement retourné une valeur
// (ici la durée du traitement)
return time;
}
/**
* Cette méthode sera toujours exécuté dans l'EDT.
* Elle recevra en paramètre les valeurs passées à publish().
* Cela peut permettre de mettre à jour l'interface pendant le traitement.
*/
@Override
protected void process(List<Double> chunks) {
// Attention : plusieurs appels à publish() peuvent être regroupés.
// Il faut donc traiter toutes les valeurs de la liste :
for (Double d : chunks) {
model.addElement(d);
}
}
/**
* Cette méthode sera toujours exécuté dans l'EDT.
* Elle est appelée dès que la méthode doInBackground() se termine
* (normalement ou pas), et permet donc d'effectuer les mises à jours
* finale sur l'interface graphique...
*/
@Override
protected void done() {
// On récupère la valeur de retour de doInBackground() :
try {
Long time = get();
// Tout s'est déroulé correctement !
JOptionPane.showMessageDialog(TestFrame.this,
"Durée du traitement : " + time + " ms");
} catch (ExecutionException e) {
// Une erreur est survenue :
JOptionPane.showMessageDialog(TestFrame.this,
"Erreur lors du traitement : " + e.getCause().getMessage(),
"Erreur",
JOptionPane.ERROR_MESSAGE);
} catch (InterruptedException e) {
// interruption reçu pendant le get()
e.printStackTrace();
}
// On restaure le bouton :
button.setEnabled(true);
// Et on supprime la JProgressBar
//progress.setVisible(false);
panel.remove(progress);
panel.revalidate();
panel.repaint();
}
};
// On ajoute une listener pour suivre l'état d'avancement du Worker
// => cela permet de mettre à jour la barre de progression.
worker.addPropertyChangeListener(new ProgressPropertyChangeListener(progress.getModel()));
// Enfin on démarre réellement le SwingWorker
worker.execute();
// Notre actionPerformed() est terminé, et l'EDT peut reprendre son traitement normal
// Toutefois notre traitement ne fait que commencer dans un thread séparé ;)
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestFrame().setVisible(true);
}
});
}
} |
Partager