2015-08-29 4 views
0

Donc, je suis relativement nouveau à java (autodidacte donc j'adorerais tout conseil/critique que vous pourriez donner) et comme pratique, j'ai décidé de créer un programme roulant avec swing en utilisant Jbuttons comme Dé. Pour simuler le lancer de dés, j'ai voulu changer aléatoirement le texte du Jbutton à des nombres différents pendant quelques secondes avant de présenter le résultat.Problème de modification du texte JButton à plusieurs reprises depuis la méthode ActionPerformed

La méthode que j'ai écrite pour faire cela a semblé fonctionner jusqu'à ce que j'essaie d'appeler si à partir de la méthode ActionPerformed. Quand je l'ai fait, le programme gèle jusqu'à la fin de la méthode, puis change le texte des boutons pour le résultat final. Je étais curieux de savoir si quelqu'un pouvait expliquer pourquoi cela se produit, ou apprenez-moi la bonne façon de faire quelque chose comme ça. Merci pour toute aide.

Bellow est un exemple rapide de la même question

package experiments.changingtext; 

    import java.awt.GridLayout; 
    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 
    import javax.swing.*; 

    public class ChangingText extends JFrame implements ActionListener{ 

    JButton button = new JButton("Change Me"); 

    public ChangingText(){ 

     this.setSize(200,200); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel pane = new JPanel(); 

     button.addActionListener(this); 
     pane.add(button); 

     this.add(pane); 

     this.setVisible(true); 

     try{Thread.sleep(500);}catch(Exception ex){} 
     //Works as expected 
     this.changeButtonText(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 

     //when run program freezes and presents the final text "change to 5" 
     if(e.getSource() == button){ 
      button.setText("change to 1"); 
      try{Thread.sleep(500);}catch(Exception ex){} 

      button.setText("change to 2"); 
      try{Thread.sleep(500);}catch(Exception ex){} 

      button.setText("change to 3"); 
      try{Thread.sleep(500);}catch(Exception ex){} 

      button.setText("change to 4"); 
      try{Thread.sleep(500);}catch(Exception ex){} 

      button.setText("change to 5"); 
     } 
    } 

    public void changeButtonText(){ 

     button.setText("change to 1"); 
      try{Thread.sleep(500);}catch(Exception ex){} 

      button.setText("change to 2"); 
      try{Thread.sleep(500);}catch(Exception ex){} 

      button.setText("change to 3"); 
      try{Thread.sleep(500);}catch(Exception ex){} 

      button.setText("change to 4"); 
      try{Thread.sleep(500);}catch(Exception ex){} 

      button.setText("change to 5"); 
    } 
} 
+2

swing utilise un seul thread pour gérer les événements et la peinture, cela signifie que nous vous utilisez Thread.sleep, vous bloquer le thread envoi d'événements, l'empêchant de peindre l'interface utilisateur. Au lieu de cela, vous pouvez utiliser un minuteur Swing – MadProgrammer

Répondre

3

Il n'y a pas besoin d'utiliser des fils de fond directement. Utilisez plutôt un minuteur Swing qui fait le compte de l'arrière-plan pour vous, et surtout, permet à tous les appels intermittents à faire sur le thread de l'événement Swing. S'il vous plaît consulter le Swing Timer Tutorial pour plus d'informations sur la façon d'utiliser cet outil très utile. En bref, vous créez un nouveau Timer dans ActionListener de JButton, donnez au Timer son propre ActionListener qui contient le code qu'il appelle plusieurs fois jusqu'à ce qu'il soit terminé.

Par exemple:

import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.util.EnumMap; 
import java.util.Map; 
import java.util.Random; 

import javax.swing.*; 

public class ChangingText2 extends JPanel { 
    private static final int PREF_W = 400; 
    private static final int PREF_H = PREF_W; 
    private static final float PTS = 24f; 
    public static final int TIMER_DELAY = 200; 
    public static final int MAX_TIME = 2000; 
    private JButton button = new JButton("1"); 

    public ChangingText2() { 
     button.setFont(button.getFont().deriveFont(Font.BOLD, PTS)); 
     button.addActionListener(new ButtonListener()); 

     setLayout(new GridBagLayout()); 
     add(button); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class ButtonListener implements ActionListener { 

     private Timer timer; 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (timer != null && timer.isRunning()) { 
       return; 
      } 
      timer = new Timer(TIMER_DELAY, new ActionListener() { 
       private int count = 0; 

       @Override 
       public void actionPerformed(ActionEvent e2) { 
        if (count * TIMER_DELAY > MAX_TIME) { 
         ((Timer) e2.getSource()).stop(); 
         return; 
        } 
        count++; 
        Die die = Die.getRandomDie(); 
        ((AbstractButton) e.getSource()).setText("" + die.getValue()); 
       } 
      }); 
      timer.start(); 
     } 
    } 

    private static void createAndShowGui() { 
     ChangingText2 mainPanel = new ChangingText2(); 

     JFrame frame = new JFrame("ChangingText2"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGui(); 
      } 
     }); 
    } 
} 

enum Die { 
    ONE(1), TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6); 
    private int value; 
    private static Random random = new Random(); 

    private Die(int value) { 
     this.value = value; 
    } 

    public int getValue() { 
     return value; 
    } 

    public static Die getRandomDie() { 
     int index = random.nextInt(Die.values().length); 
     return Die.values()[index]; 
    } 

}