Lorsque l'on souhaite utiliser SwingWorker afin d'effectuer un traitement mais sans bloquer son interface graphique, on peut être confronter au problème de la communication de son thread de traitement(SwingWorker) vers l'interface graphique.
J'explique :
Ci-dessous notre classe qui étends de SwingWorker
Notre classe avec l'interface graphique :
Et l'interface qui permet de mettra à jour le composant graphique :
C'est la méthode "publish" qui se trouve dans le "doInBackGround" qui permet de mettre à jour le composant graphique.
A noter que dans la méthode "messageChanged" de l'interface "Informable", nous somme obliger d'utiliser ceci :
Si l'on utilise pas ceci, on obtient une erreur AWT-EventQueue-0 thread Invalid thread access, puisque le thread du SwingWorker va essayer d'aller modifier un composant graphique qui est lui-même géré par un autre Thread dont il n'aura pas accès (lien expliquant ce comportement http://www.eclipse.org/swt/faq.php#uithread )
J'explique :
Ci-dessous notre classe qui étends de SwingWorker
public class MySwingWork extends SwingWorker<Integer, String>
{
private final Informable informable;
public MySwingWork (Informable informable)
{
this.informable = informable;
}
@Override
protected Integer doInBackground() throws Exception
{
/* WORK */
//C'est cette méthode qui mettra à jour le textArea
publish("test");
return null;
}
@Override
protected void process(List<String> strings)
{
for (String s : strings)
informable.messageChanged(s);
}
}
{
private final Informable informable;
public MySwingWork (Informable informable)
{
this.informable = informable;
}
@Override
protected Integer doInBackground() throws Exception
{
/* WORK */
//C'est cette méthode qui mettra à jour le textArea
publish("test");
return null;
}
@Override
protected void process(List<String> strings)
{
for (String s : strings)
informable.messageChanged(s);
}
}
Notre classe avec l'interface graphique :
public class monIHM extends JFrame
{
public void init()
{
/*Initialisation de l'interface graphique*/
//Text Area qui sera mis à jour pendant le traitement du SwingWorker
JTextArea textArea=new JTextArea();
//Interface qui permettra de mettre à jour l'UI en direct avec le swingWorker
Informable informable = new Informable()
{
@Override
public void messageChanged(String message)
{
final String s = message;
Display.getDefault().syncExec(new Runnable()
{
public void run()
{
//Modification du TextArea
textArea.setText(s);
}
});
}
};
MySwingWork mySwingWork=new MySwingWork(interface);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
/* Démarrage du SwingWorker. */
mySwingWork.execute();
}
});
}
}
{
public void init()
{
/*Initialisation de l'interface graphique*/
//Text Area qui sera mis à jour pendant le traitement du SwingWorker
JTextArea textArea=new JTextArea();
//Interface qui permettra de mettre à jour l'UI en direct avec le swingWorker
Informable informable = new Informable()
{
@Override
public void messageChanged(String message)
{
final String s = message;
Display.getDefault().syncExec(new Runnable()
{
public void run()
{
//Modification du TextArea
textArea.setText(s);
}
});
}
};
MySwingWork mySwingWork=new MySwingWork(interface);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
/* Démarrage du SwingWorker. */
mySwingWork.execute();
}
});
}
}
Et l'interface qui permet de mettra à jour le composant graphique :
public interface Informable
{
void messageChanged(String message);
}
{
void messageChanged(String message);
}
C'est la méthode "publish" qui se trouve dans le "doInBackGround" qui permet de mettre à jour le composant graphique.
A noter que dans la méthode "messageChanged" de l'interface "Informable", nous somme obliger d'utiliser ceci :
Display.getDefault().syncExec(new Runnable()
{
public void run()
{
//Modification du TextArea
textArea.setText(s);
}
{
public void run()
{
//Modification du TextArea
textArea.setText(s);
}
Si l'on utilise pas ceci, on obtient une erreur AWT-EventQueue-0 thread Invalid thread access, puisque le thread du SwingWorker va essayer d'aller modifier un composant graphique qui est lui-même géré par un autre Thread dont il n'aura pas accès (lien expliquant ce comportement http://www.eclipse.org/swt/faq.php#uithread )