2015-08-29 2 views
0

Так что я относительно новичок в java (сам преподавал, поэтому мне бы понравились любые советы/критические замечания, которые вы могли бы дать), и, как практика, я решил создать программу для прокатки кости с помощью swing с помощью Jbuttons as Игральная кость. Чтобы имитировать прокачку кубиков, я хотел случайно изменить текст Jbutton на разные числа за несколько секунд до представления результата.Редактирование проблемы JButton текст неоднократно изнутри ActionPerformed метод

Метод, который я написал для этого, по-видимому, работал до тех пор, пока я не попытался вызвать, если из метода ActionPerformed. Когда я это сделал, программа замерзнет до конца метода, а затем изменит текст кнопок на конечный результат.

Мне было любопытно, может ли кто-нибудь объяснить, почему это происходит, или научить меня правильно делать что-то подобное. Спасибо за любую помощь.

пыльник быстрый пример того же вопроса

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

Качели использует один поток для управления событиями и живописи, это означает, что мы вы используете Thread.sleep, вы блокирование событий потока диспетчеризации, предотвращая его от живописи в пользовательском интерфейсе. Вместо этого вы можете использовать таймер Swing – MadProgrammer

ответ

3

Там нет необходимости использовать фоновые потоки непосредственно. Скорее используйте таймер Swing, который делает подсчет фона для вас, и, самое главное, разрешает все прерывистые вызовы в потоке событий Swing. Пожалуйста, ознакомьтесь с Swing Timer Tutorial для получения дополнительной информации о том, как использовать этот очень полезный инструмент. Вкратце, вы создаете новый таймер в ActionListener JButton, даете таймеру свой собственный ActionListener, который содержит код, который он называет повторно, до завершения.

Например:

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]; 
    } 

}