Java Таймер обратного отсчета с определенного времени - PullRequest
0 голосов
/ 29 января 2020

с использованием Java и Java Swing для GUI. Сценарий состоит в том, что я хочу, чтобы пользователь ввел желаемое время (в JTextbox) в формате ЧЧ: ММ: СС, и с этого времени отсчет времени по секундам, пока он не достигнет нуля. В настоящее время я использую таймер и функцию timer.between. Я создаю Instant () из времени ввода пользователя, а также использую Instant.now (). Моменты создаются, однако, часы обратного отсчета не отсчитывают время от ввода пользователя, а скорее случайные числа, которые я не могу понять, откуда они берутся. Кто-нибудь еще может увидеть проблему?

 javax.swing.Timer countDown = new javax.swing.Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Duration countingDown = Duration.between(Instant.now(), userInputCountDown);
                autoShutOffTF.setText(String.format("%02d:%02d:%02d",
                        countingDown.toHours(),
                        countingDown.toMinutes() % 60,
                        countingDown.getSeconds() % 60));
            }
        });
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //Getting user input, parsing String in the form of HH:MM:SS 
                String countdownInput = autoShutOffTF.getText();

                String getHours = countdownInput.substring(0,2);
                int hours = Integer.parseInt(getHours);

                String getMins = countdownInput.substring(3,5);
                int mins = Integer.parseInt(getMins);

                String getSecs = countdownInput.substring(6,8);
                int seconds = Integer.parseInt(getSecs);

                //Creating a date instance, to get the current year, month and date
                Date date = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                int year = calendar.get(Calendar.YEAR);
                int month = calendar.get(Calendar.MONTH);
                int day = calendar.get(Calendar.DAY_OF_MONTH);

                //creating a new calendar with all of the data
                Calendar cal = Calendar.getInstance();
                cal.set(year, month, day, hours, mins, seconds);

                //creating a new instant with the new calendar with all of the data
                userInputCountDown = cal.toInstant();

                //starting timer
                countDown.start();
            }
        });

1 Ответ

2 голосов
/ 29 января 2020

Не используйте Date или Calendar, API java.time более способен достичь того, что вы хотите.

Глядя на это ...

Date date = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);

//creating a new calendar with all of the data
Calendar cal = Calendar.getInstance();
cal.set(year, month, day, hours, mins, seconds);

Вы создаете новое время, основываясь на часах / минутах / секундах, но, что меня беспокоит, так это то, что происходит, если время меньше, чем сейчас? Это может быть проблема, с которой вы столкнулись.

Итак, вы можете захотеть проверить, указано ли время до или после текущего времени, и соответственно изменить день - при условии, что вы хотите использовать абсолютное время (ie создайте таймер, который отсчитывает время до 18:00)

Это ...

Duration countingDown = Duration.between(Instant.now(), userInputCountDown);

мне тоже кажется неправильным, так как userInputCountDown должен быть в будущее

В следующем примере используется несколько иной подход, поскольку он создает «таймер», который создаст цель в будущем (на основе входных данных) из текущего времени (добавление часов, минут и секунд). ) и использовать его как опорную точку для обратного отсчета.

Итак, вы можете сказать, например, «создать 1-часовой» таймер.

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;

class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextField targetHours;
        private JTextField targetMins;
        private JTextField targetSeconds;

        private Instant futureTime;
        private Timer timer;

        private JLabel countDown;

        public TestPane() {

            setLayout(new GridBagLayout());

            targetHours = new JTextField("00", 2);
            targetMins = new JTextField("00", 2);
            targetSeconds = new JTextField("00", 2);

            JPanel targetPane = new JPanel(new GridBagLayout());
            targetPane.add(targetHours);
            targetPane.add(new JLabel(":"));
            targetPane.add(targetMins);
            targetPane.add(new JLabel(":"));
            targetPane.add(targetSeconds);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(8, 8, 8, 8);

            add(targetPane, gbc);

            JButton btn = new JButton("Start");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    futureTime = LocalDateTime.now()
                            .plusHours(Long.parseLong(targetHours.getText()))
                            .plusMinutes(Long.parseLong(targetMins.getText()))
                            .plusSeconds(Long.parseLong(targetSeconds.getText()))
                            .atZone(ZoneId.systemDefault()).toInstant();

                    if (timer != null) {
                        timer.stop();
                    }

                    countDown.setText("---");
                    timer = new Timer(500, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            Duration duration = Duration.between(Instant.now(), futureTime);
                            if (duration.isNegative()) {
                                timer.stop();
                                timer = null;
                                countDown.setText("00:00:00");
                            } else {
                                String formatted = String.format("%02d:%02d:%02d", duration.toHours(), duration.toMinutesPart(), duration.toSecondsPart());
                                countDown.setText(formatted);
                            }
                        }
                    });
                    timer.start();
                }
            });

            add(btn, gbc);

            countDown = new JLabel("---");
            add(countDown, gbc);
        }

    }

}

WARNING - Я не проверяю входные данные, поэтому вам нужно быть осторожным.

Если вместо этого вы хотите выполнить обратный отсчет до определенного момента времени (ie отсчет с настоящего времени до 18:00). ), тогда вам нужно будет использовать цепочку LocalDateTime#withHour(Long)#withMinute(Long)#withSecond(Long). Но, будьте осторожны, вам придется проверить, наступило ли время в будущем или прошлом, и предпринять соответствующие действия, потому что, если вы хотите отсчитывать время до 6 вечера, но это 7 вечера ... что это на самом деле означает: /?

...