À l'aide d'une boucle de fil de mise à jour d'une JFrame
ive fait de la vaste recherche sur l'utilisation de threads dans une boucle et tandis que je comprends le concept comment séparer les threads de travail, j'ai encore cant semblent saisir comment l'implémenter dans mon application simple.
Mon application consiste en un formulaire avec une zone de texte. Cette zone de texte doit être mis à jour une fois de plus itération d'une boucle. Il commence avec la presse sur un bouton, mais la boucle doit aussi terminer avec la presse d'un bouton d'arrêt. Ive a utilisé une valeur booléenne à suivre si sa été pressé.
Voici mon code du formulaire:
package threadtester;
public class MainForm extends javax.swing.JFrame {
public MainForm() {
initComponents();
}
private void RunButtonActionPerformed(java.awt.event.ActionEvent evt) {
ThreadTester.setRunnable(true);
ThreadTester example = new ThreadTester(2,this);
example.run();
}
private void StopButtonActionPerformed(java.awt.event.ActionEvent evt) {
ThreadTester.setRunnable(false);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainForm().setVisible(true);
}
});
}
public void setTextBox(String myString){
MainTextbox.setText(myString);
}
}
Comme vous pouvez le voir, j'ai un bouton est pressé. Lorsque le bouton est enfoncé, ce exécute le code c'est dans une autre classe appelée ThreadTester. Voici le code de cette classe:
package threadtester;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ThreadTester implements Runnable
{
int thisThread;
MainForm myMainForm;
private static boolean runnable;
//constructor
public ThreadTester (int number,MainForm mainForm)
{
thisThread = number;
myMainForm = mainForm;
}
public void run ()
{
for (int i =0;i< 20; i++) {
if(runnable==false){
break;
}
System.out.println("I'm in thread " + thisThread + " line " + i);
myMainForm.setTextBox(i + "counter");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTester.class.getName()).log(Level.SEVERE, null, ex);
}
} }
public static void setRunnable(Boolean myValue){
runnable = myValue;
}
public static void main(String[] args) {
MainForm.main(args);
}
}
comme vous pouvez le voir, la boucle a été créé sur un autre fil... mais la zone de texte uniquement les mises à jour après la boucle est terminée. Maintenant que im courant dans mon MainForm j'ai créé un sujet séparé pour exécuter la boucle, donc je ne comprends pas pourquoi sa ne fonctionne pas? Tout conseils seront très appréciés, j'ai essayé de chercher des exemples sur la pile d'échange, mais je ne peux pas sembler obtenir à l'intégrer dans ma implemntation.
Avec la recommandation proposée par Tassos ma méthode run ressemble maintenant à ceci:
public void run ()
{
for (int i =0;i< 20; i++) {
if(runnable==false){
break;
}
System.out.println("I'm in thread " + thisThread + " line " + i);
final String var = i + "counter";
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
myMainForm.setTextBox(var);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTester.class.getName()).log(Level.SEVERE, null, ex);
}
} }
OriginalL'auteur Festivejelly | 2013-06-14
Vous devez vous connecter pour publier un commentaire.
Pour Tassos réponse au travail, vous avez réellement à créer un nouveau fil de discussion, que vous n'avez pas faites. Simplement en appelant
n'est pas assez, sice qui appelle simplement la
run
méthode à partir d'EDT. Vous devez faire ce qui suit:Veuillez vous référer à Définition et lancement d'un Thread.
Aussi, vous souhaitez modifier le même terrain, avec deux threads différents (
runnable
), qui est un bug. Vous devez en savoir plus sur java simultanéité.-1: mise à jour de l'INTERFACE utilisateur doit être fait sur l'EDT que le Swing n'est pas thread-safe @NicholasJohn Alors que cela fonctionne sur un petit programme comme celui-là, il est probable d'avoir des problèmes, si ce n'est les blocages, plus tard.
ma réponse est une augmentation de l'un Tassos fourni. Je ne vois pas où EDT swing mises à jour ont lieu, après nos deux correctifs sont appliqués.
Désolé, mais c'est assez difficile de votre réponse que vous êtes réellement emballer vos appels dans un
invokeLater
-bloc d'appel. En outre, une BalançoireTimer
serait alors plus approprié avec un simple code.Je pense que
In order for Tassos's answer to work
est assez clair, mais je suis totalement d'accord sur le swing timer. L'OP voulait savoir pourquoi il n'a toujours pas de travail après avoir essayé la plupart des upvoted réponse à l'époque, il a même édité sa question pour en tenir compte.OriginalL'auteur predi
Modifier cette ligne
en
Pourquoi? Parce que vous ne pouvez pas faire de l'INTERFACE utilisateur de travailler en non-INTERFACE threads.
Mais il est sur le EDT. En fait, c'est le problème, est en boucle sur l'EDT, alors qu'il devrait le faire à l'extérieur de l'EDT.
Ouais, ma réponse est en fait mal.
OriginalL'auteur Tassos Bassoukos
Le problème, c'est que vous êtes le blocage de l'EDT (Événement Expédition Fil), la prévention de l'INTERFACE utilisateur pour rafraîchir jusqu'à ce que votre boucle est terminée.
Les solutions à ces problèmes est toujours le même, l'utilisation d'un Swing
Timer
ou utiliser unSwingWorker
.Voici un exemple de l'utilisation d'un
SwingWorker
:OriginalL'auteur Guillaume Polet