JLabel отображает обратный отсчет, Java

У меня есть "статус" JLabel в одном классе (с именем Welcome) и таймер в другом (с именем Timer). Прямо сейчас, первый отображает слово "статус", а второй должен делать обратный отсчет. Я бы так хотел, но не знаю, как отобразить 10, 9, 8, 7 ... 0 (и перейти к следующему окну). Мои попытки пока:

// class Welcome

setLayout(new BorderLayout());
JPanel area = new JPanel();
JLabel status = new JLabel("status");
area.setBackground(Color.darkGray);
Font font2 = new Font("SansSerif", Font.BOLD, 25);
status.setFont(font2);
status.setForeground(Color.green);      
area.add(status, BorderLayout.EAST); // can I put it in the bottom-right corner?
this.add(area);

и таймер:

 public class Timer implements Runnable {

//  public void runThread() {
//      new Thread(this).start();
//  }

public void setText(final String text) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            setText(text); // link to status here I guess
        }
    });
}

public void run() {
    for (int i = 10; i > 0; i--) {
        // set the label
        final String text = "(" + i + ") seconds left";
        setText(text);

//          // sleep for 1 second
//          try {
//              Thread.currentThread();
//              Thread.sleep(1000);
//          } catch (Exception ex) {
//          }
    }
    // go to the next window
    UsedBefore window2 = new UsedBefore();
    window2.setVisible(true);
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    // runThread();
}

} // end class

4 ответа

Решение

Я согласен, что вам следует рассмотреть возможность использования таймера "Java" в соответствии с Anh Pham, но на самом деле доступно несколько классов Timer, и для ваших целей таймер Swing, а не java.util.Timer, как предложено Anh, подойдет для ваших целей. Лучший.

Что касается вашей проблемы, то на самом деле это не более чем простая проблема ссылок. Дайте классу с меткой публичный метод, скажем setCountDownLabelText(String text)и затем вызовите этот метод из класса, который содержит таймер. Вам нужно иметь ссылку на класс GUI с таймером JLabel в другом классе.

Например:

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Welcome extends JPanel {
   private static final String INTRO = "intro";
   private static final String USED_BEFORE = "used before";
   private CardLayout cardLayout = new CardLayout();
   private JLabel countDownLabel = new JLabel("", SwingConstants.CENTER);

   public Welcome() {
      JPanel introSouthPanel = new JPanel();
      introSouthPanel.add(new JLabel("Status:"));
      introSouthPanel.add(countDownLabel);

      JPanel introPanel = new JPanel();
      introPanel.setPreferredSize(new Dimension(400, 300));
      introPanel.setLayout(new BorderLayout());
      introPanel.add(new JLabel("WELCOME", SwingConstants.CENTER), BorderLayout.CENTER);
      introPanel.add(introSouthPanel, BorderLayout.SOUTH);

      JPanel usedBeforePanel = new JPanel(new BorderLayout());
      usedBeforePanel.setBackground(Color.pink);
      usedBeforePanel.add(new JLabel("Used Before", SwingConstants.CENTER));

      setLayout(cardLayout);
      add(introPanel, INTRO);
      add(usedBeforePanel, USED_BEFORE);

      new HurdlerTimer(this).start();
   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("Welcome");
      frame.getContentPane().add(new Welcome());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }

   public void setCountDownLabelText(String text) {
      countDownLabel.setText(text);
   }

   public void showNextPanel() {
      cardLayout.next(this);
   }
}

class HurdlerTimer {
   private static final int TIMER_PERIOD = 1000;
   protected static final int MAX_COUNT = 10;
   private Welcome welcome; // holds a reference to the Welcome class
   private int count;

   public HurdlerTimer(Welcome welcome) {
      this.welcome = welcome; // initializes the reference to the Welcome class.
      String text = "(" + (MAX_COUNT - count) + ") seconds left";
      welcome.setCountDownLabelText(text);
   }

   public void start() {
      new Timer(TIMER_PERIOD, new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            if (count < MAX_COUNT) {
               count++;
               String text = "(" + (MAX_COUNT - count) + ") seconds left";
               welcome.setCountDownLabelText(text); // uses the reference to Welcome
            } else {
               ((Timer) e.getSource()).stop();
               welcome.showNextPanel();
            }
         }
      }).start();
   }

}

Поскольку вы используете Swing, вы должны использовать javax.swing.Timer, а не java.util.Timer. Вы можете установить таймер на срабатывание с интервалом в 1 секунду (1000 мс), и ваш слушатель сделает обновление. Поскольку обновления Swing должны происходить в потоке рассылки событий, ваш слушатель является идеальным местом для status.setText,

В Java уже есть класс Timer: http://www.exampledepot.com/egs/java.util/ScheduleRepeat.html

Почему бы не поместить метод setText в класс приветствия и просто сделать "status.setText(text)"?

И вы можете попробовать BorderLayout.SOUTH или.PAGE END или.LINE END, чтобы получить таймер в правом нижнем углу

Другие вопросы по тегам