@Skelorc
Начинающий разработчик.

Как сделать обратный отсчет времени в java swing?

Написал небольшую программу в java используя swing. В одном месте, программа должна выводить в jTextfield отсчет секунд от 3 до 0, затем сообщение старт. Пытался с помощью такой конструкции:
for(int i = 3, i > o; i--)
{ jTextfield.setText("Осталось: " + i);
Thread.sleep(1000);
}

Все это приписывалось внутри jButton, т.е. при нажатии мышкой на кнопку jButton. Короче, вся программа висела эти самые 3 секунды, а потом в jTextfield вышло 1, и все на этом. Также пытался с Timer и TimerTask, но там тоже не срослось. Как мне решить эту проблему, помогите а.
  • Вопрос задан
  • 1419 просмотров
Решения вопроса 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Java
Седой и строгий
При создании окна создаётся Event Dispatch Thread, внутри которого крутится бесконечный цикл, на каждой итерации достающий событие из очереди и запускающий обработчик для него. В обработчике бесполезно использовать циклы для изменения интерфейса, так как все изменения просто встанут в очередь и будут выполнены только на одной из следующих итераций цикла событий. И тем более нельзя останавливать Поток Обработки Событий (что вы делаете вызовом Thread.sleep(1000)), это заморозит всё приложение. Поэтому необходимо использовать предлагаемые библиотекой механизмы запуска фоновых задач и взаимодействия с ними. Например такие, как SwingUtilities.invokeLater(), Timer и SwingWorker.
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.Timer;

public class Countdown {
    private final JLabel label = new JLabel("...");
    private final JButton button = new JButton("Click me");
    private final Timer timer;
    private int count = 3;

    public Countdown() {
        timer = new Timer(1000, e -> {
            if (count > 0) {
                label.setText(String.valueOf(count--));
            } else {
                ((Timer) (e.getSource())).stop();
                count = 3;
                button.setEnabled(true);
            }
        });
        timer.setInitialDelay(0);

        button.addActionListener(e -> {
            timer.start();
            button.setEnabled(false);
        });

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(label, BorderLayout.PAGE_START);
        frame.add(button, BorderLayout.PAGE_END);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new Countdown();
    }
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
alfss
@alfss
https://career.habr.com/alfss
Нужен отдельный поток для таймера
Ответ написан
надо нпр тк

public void mouseReleased(MouseEvent mouseEvent) {
				if (SwingUtilities.isLeftMouseButton(mouseEvent)) {
					System.out.println("Left button released.");
					System.err.println("Counting down from " + i);

					// NOTE: SwingUtilities.invokeLater shows only the last update of the
					// text
					// SwingUtilities.invokeLater(new Runnable() {
					// });
					Runnable r = new Runnable() {
						@Override
						public void run() {
							final int progress = i;
							for (int cnt = progress; cnt > 0; cnt--) {
								final int current = cnt;
								String buttonText = String.format("Calculated %d of %d",
										current, progress);
								button.setVisible(false);
								button.setText(buttonText);
								button.doLayout();
								button.setVisible(true);
								System.err.println("updated butto text to " + buttonText);
								try {
									Thread.sleep(300);
								} catch (InterruptedException e) {
									System.err.println("Exception (ignored): " + e.toString());
								}
							}
						}
					};
					Thread t = new Thread(r);
					t.start();
				}


многочисленные переприсвоения - экспериментировал с invokeLater - почистите саме пл
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы