多个Swing计时器导致多个动作发生

时间:2014-01-22 02:06:56

标签: java swing timer

我正在做一个Java项目,我必须制作一个包含多个从用户输入时间倒计时的计时器的GUI。当我只创建一个计时器时,程序工作正常,但是当我尝试包含多个计时器时,每个计时器将根据计时器的数量更快地倒计时。我认为问题是每次swing定时器调用一个动作时多次调用ActionListener引起的,但我不知道如何解决这个问题。

这是我的CountDownTimer类,它包含计时器的属性和方法:

package pack1;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;

/*******************************************************************************
 * Class that contains the methods needed to create a timer that counts down
 * @version January 2014, Project 1
 ********************************************************************************/
public class CountDownTimer {
    /** Amount of hours that are being counted down in the timer */
    int hours;
    /** Amount of minutes that are being counted down in the timer */
    int minutes;
    /** Amount of seconds that are being counted down in the timer */
    int seconds;

    /** Boolean that determines if the add method will work. It is changed with the toggleSuspend method */
    static boolean toggle = false;

    /*****************************************************************************************
     * Default constructor that creates a CountDownTimer object with no time contained in it
     *****************************************************************************************/
    public CountDownTimer() {
        hours = 0;
        minutes = 0;
        seconds = 0;
    }

    /*********************************************************************************************
     * Constructor that uses the input amount of hours, minutes, and seconds to count down from
     * 
     * Does not allow time that is negative or allow seconds or minutes that are over 60
     * @param hours amount of hours that will be counted down from
     * @param minutes amount of minutes that will be counted down from
     * @param seconds amount of seconds that will be counted down from
     *********************************************************************************************/
    public CountDownTimer(int hours, int minutes, int seconds) {
        super();

        // doesn't allow negative minutes, seconds, or hours
        if (seconds < 0 || minutes < 0 || hours < 0) {
            throw new IllegalArgumentException("Time cannot be negative");
        }
        // doesn't allow seconds that are higher than 60
        if (seconds >= 60) {
            throw new IllegalArgumentException(
                    "Cannot have more than 60 seconds");
        }
        // doesn't allow minutes that are higher than 60
        if (minutes >= 60) {
            throw new IllegalArgumentException(
                    "Cannot have more than 60 minutes");
        }
        this.hours = hours;
        this.minutes = minutes;
        this.seconds = seconds;
    }
    /*********************************************************************
     * Constructor that takes minutes and seconds, and sets hours to zero
     * also doesn't allow minutes or seconds to be negative or above 60
     * @param minutes amount of minutes that will be counted down from
     * @param seconds amount of seconds that will be counted down from
     *************************************************************************/
    public CountDownTimer(int minutes, int seconds) {
        super();
        // doesn't allow seconds minutes or hours to be negative
        if (seconds < 0 || minutes < 0 || hours < 0) {
            throw new IllegalArgumentException("Time cannot be negative");
        }
        // doesn't allow seconds to be greater than 60
        if (seconds >= 60) {
            throw new IllegalArgumentException(
                    "Cannot have more than 60 seconds");
        }
        // doesn't allow minutes to be greater than 60
        if (minutes >= 60) {
            throw new IllegalArgumentException(
                    "Cannot have more than 60 minutes");
        }

        this.hours = 0;
        this.minutes = minutes;
        this.seconds = seconds;
    }

    /***********************************************************************
     * Constructor that only takes seconds and sets hours and minutes to 0
     * does not allow the seconds to be above 60 or negative
     * @param seconds amount of seconds that will be counted down from
     *************************************************************************/
    public CountDownTimer(int seconds) {
        super();

        // doesn't allow seconds minutes or hours to be negative
        if (seconds < 0 || minutes < 0 || hours < 0) {
            throw new IllegalArgumentException("Time cannot be negative");
        }
        // doesn't allow seconds to be greater than 60
        if (seconds >= 60) {
            throw new IllegalArgumentException(
                    "Cannot have more than 60 seconds");
        }
        this.hours = 0;
        this.minutes = 0;
        this.seconds = seconds;
    }


    /** 
     * Constructor that clones one CountDownTimer object into a new CountDownTimer object
     * @param other The CountDownTimer object that is being cloned
     * */
    public CountDownTimer(CountDownTimer other) {
        this.hours = other.hours;
        this.minutes = other.minutes;
        this.seconds = other.seconds;
    }

    /*******************************************************************************************************************************
     * Constructor that converts a string in the format of "00:00:00" into seconds minutes and hours so it can be counted down from
     * @param startTime String that is converted into seconds minutes and hours
     *******************************************************************************************************************************/
    public CountDownTimer(String startTime) {
        // Separates the seconds minutes and hours into an array
        String[] parts = startTime.split(":");
        // if the array has only one cell, that means only seconds were input
        if (parts.length == 1) {
            seconds = Integer.parseInt(parts[0]);
        }
        // if the array has only 2 cells that means there is only minutes and seconds input
        if (parts.length == 2) {
            minutes = Integer.parseInt(parts[0]);
            seconds = Integer.parseInt(parts[1]);
        }
        // if the array has 3 cells that means there is seconds minutes and hours input
        if (parts.length == 3) {
            hours = Integer.parseInt(parts[0]);
            minutes = Integer.parseInt(parts[1]);
            seconds = Integer.parseInt(parts[2]);
        }
        // doesn't allow seconds minutes or hours to be negative
        if (seconds < 0 || minutes < 0 || hours < 0) {
            throw new IllegalArgumentException("Time cannot be negative");
        }
        // doesn't allow seconds to be greater than or equal to 60
        if (seconds >= 60) {
            throw new IllegalArgumentException(
                    "Cannot have more than 60 seconds");
        }
        // doesn't allow minutes to be greater than or equal to 60
        if (minutes >= 60) {
            throw new IllegalArgumentException(
                    "Cannot have more than 60 minutes");
        }
    }

    /**************************************************************************************************
     * Method that returns true or false based on whether or not two CountDownTimer objects are equal
     * @param other Object that is being compared to another CountDownTimer
     **************************************************************************************************/
    public boolean equals(Object other) {
        // converts the two objects to seconds then compares them
        if (this.convertToSeconds() == ((CountDownTimer) other)
                .convertToSeconds())
            return true;
        return false;
    }

    /********************************************************************************
     * Returns a boolean based on whether two CountDownTimers, t1 and t2, are equal
     * @param t1 first CountDownTimer being compared
     * @param t2 second CountDownTimer being compared
     ********************************************************************************/
    public static boolean equals(CountDownTimer t1, CountDownTimer t2) {
        // converts the two objects to seconds and then compares them
        if (t1.convertToSeconds() == t2.convertToSeconds())
            return true;
        return false;
    }

    /************************************************************************************************
     * Compares to CountDownTimer objects and returns an int 1, 0, or -1 based on whether the first
     * object is greater than, equal to, or less than the CountDownTimer in the parameter
     * @param other CountDownTimer that is being compared
     *************************************************************************************************/
    public int compareTo(CountDownTimer other) {
        if (this.convertToSeconds() > other.convertToSeconds())
            return 1;
        else if (this.convertToSeconds() < other.convertToSeconds())
            return -1;
        return 0;
    }

    /**************************************************************************************************
     * Compares to CountDownTimer objects and returns an int 1, 0, or -1 based on whether the first
     * object (t1) is greater than, equal to, or less than the second object (t2)
     * @param t1 first object being compared
     * @param t2 second object being compared
     * @return
     ***************************************************************************************************/
    public static int compareTo(CountDownTimer t1, CountDownTimer t2) {
        if (t1.convertToSeconds() > t2.convertToSeconds())
            return 1;
        else if (t1.convertToSeconds() < t2.convertToSeconds())
            return -1;
        return 0;
    }

    /***************************************************************
     * subtracts the input amount of seconds from a CountDownTimer
     * @param seconds amount of seconds the user wants to subtract
     ***************************************************************/
    public void subtract(int seconds) {
        // places the amount of seconds into an integer
        int tempSeconds = this.convertToSeconds();
        // subtracts the input seconds from the seconds that were converted
        tempSeconds -= seconds;
        // converts the new seconds back into the object
        formatSeconds(tempSeconds);
    }


    /*******************************************************************************************
     * Subtracts the amount of time contained in one CountDownTimer from another CountDownTimer
     * @param other CountDownTimer that is doing the subtracting
     *******************************************************************************************/
    public void subtract(CountDownTimer other) {
        int otherSeconds = other.convertToSeconds();
        this.subtract(otherSeconds);
    }

    /***********************************************************************
     * Adds seconds to the object based on what is put into the parameter
     * @param seconds amount of seconds being added to the CountDownTimer
     ************************************************************************/
    public void add(int seconds) {
        // keeps the method from adding when the toggle is activated
        if (toggle == false) {
            int tempSeconds = this.convertToSeconds();
            tempSeconds += seconds;
            formatSeconds(tempSeconds);
        } else
            throw new IllegalArgumentException(
                    "Cannot use add when toggle is enabled");
    }
/**
 * Adds the seconds from one CountDownTimer to another CountDownTimer
 * @param other CountDownTimer that is being added to another CountDowntimer
 */
    public void add(CountDownTimer other) {
        // doesn't allow the method to add when the toggle is true
        if (toggle == false) {
            int otherSeconds = other.convertToSeconds();
            this.add(otherSeconds);
        } else
            throw new IllegalArgumentException(
                    "Cannot use add when toggle is enabled");
    }

    /*******************************************
     * Decreases the CountDownTimer by 1 second
     *******************************************/
    public void dec() {
        int tempSeconds = this.convertToSeconds();
        tempSeconds--;
        formatSeconds(tempSeconds);
    }

    /****************************************************
     * Increases the CountDownTimer object by 1 second
     ***************************************************/
    public void inc() {
        int tempSeconds = this.convertToSeconds();
        tempSeconds--;
        formatSeconds(tempSeconds);
    }

    /**
     * Returns the object as a string in the format of "00:00:00"
     */
    public String toString() {
        String time = "" + this.hours + ":";
        if (this.minutes < 10) {
            time += "0" + this.minutes + ":";
        } else {
            time += this.minutes + ":";
        }
        if (this.seconds < 10) {
            time += "0" + this.seconds;
        } else {
            time += this.seconds;
        }
        return time;
    }

    /************************************************
     * Saves the object with a specified name
     * @param fileName name of the file being saved
     *************************************************/
    public void save(String fileName) {
        PrintWriter out = null;
        try {
            out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        out.println(this.hours);
        out.println(this.minutes);
        out.println(this.seconds);
        out.close();
    }
/**************************************************
 * Loads the object with the specified name
 * @param fileName Name of the file being loaded
 **************************************************/
    public void load(String fileName) {
        try {
            Scanner fileReader = new Scanner(new File(fileName));

            this.hours = fileReader.nextInt();
            this.minutes = fileReader.nextInt();
            this.seconds = fileReader.nextInt();

            fileReader.close();
            System.out.println("Hours: " + this.hours);
            System.out.println("Minutes: " + this.minutes);
            System.out.println("Seconds: " + this.seconds);
        } catch (FileNotFoundException error) {
            System.out.println("File not found");
        } catch (IOException error) {
            System.out.println("OH NO THAT WAS NOT SUPPOSED TO HAPPEN");
        }
    }
/**********************************************************************************************
 * Switches the toggle boolean, and doesn't allow the add methods to work when it is activated
 ************************************************************************************************/
    public static void toggleSuspend() {
        if (toggle == false)
            toggle = true;
        if (toggle == true)
            toggle = false;
    }

    /***********************************************************************************
     * Formats a certain amount of seconds and puts it into an existing CountDownTimer
     * @param seconds seconds being formatted
     ***********************************************************************************/
    private void formatSeconds(int seconds) {
        this.hours = seconds / 3600;
        seconds %= 3600;
        this.minutes = seconds / 60;
        this.seconds = seconds % 60;
    }

    /*****************************************************************************
     * Returns the amount of seconds that are contained in a CountDownTime object
     *****************************************************************************/
    private int convertToSeconds() {
        int hSeconds = hours * 3600;
        int mSeconds = minutes * 60;
        return hSeconds + mSeconds + seconds;
    }
}

这是我的GUI面板课,我遇到了问题。我正在使用数组来制作多个计时器。

package pack1;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;

public class MyTimerPanel extends JPanel {
    /** Array of CountDownTimers that will be used */
    private CountDownTimer[] cdt;

    /** Array of Timer objects that are used to count down by 1 every second*/
    private Timer[] javaTimer;
    /** Array of TimerListeners that are called in the Timer objects */
    private TimerListener timer[];

    /** Array of JPanels that will hold each timer interface */
    private JPanel[] panel;
    /** Array of JLabels for the display of time, seconds, minutes, and hours */
    private JLabel[] timeDisplay, secDisplay, minDisplay, hourDisplay;
    /** Array of JButtons that start, stop, and set the timer */
    private JButton[] start, stop, set;
    /** Array of JTextFields that the user will input the seconds, minutes, and hours*/
    private JTextField[] sec, min, hour;

    /** Array of booleans that will determine if the timer should be counting down */ 
    private boolean[] go;

    /** Amount of milliseconds the timer needs to wait before performing an action */
    private final int DELAY = 1000;

    /** Amount of CountDownTimers in the interfaces */ 
    private final int AMOUNT = 3;

    // test integer
    int[] count;


    /******************************************************************************************
     * Constructor that sets the lengths of the arrays and instantiates each part of the array
     ******************************************************************************************/
    public MyTimerPanel() {
        count = new int[AMOUNT];
        timer = new TimerListener[AMOUNT];
        cdt = new CountDownTimer[AMOUNT];
        javaTimer = new Timer[AMOUNT];
        panel = new JPanel[AMOUNT];
        timeDisplay = new JLabel[AMOUNT];
        secDisplay = new JLabel[AMOUNT];
        minDisplay = new JLabel[AMOUNT];
        hourDisplay = new JLabel[AMOUNT];
        sec = new JTextField[AMOUNT];
        min = new JTextField[AMOUNT];
        hour = new JTextField[AMOUNT];
        start = new JButton[AMOUNT];
        stop = new JButton[AMOUNT];
        set = new JButton[AMOUNT];
        go = new boolean[AMOUNT];
        // Defines each part of each array and adds the neccessary components to the buttons and panels
        for (int i = 0; i < AMOUNT; i++) {
            count[i] = 0;
            cdt[i] = new CountDownTimer(0, 0, 0);
            go[i] = false;
            timer[i] = new TimerListener();
            javaTimer[i] = new Timer(DELAY, timer[i]);
            javaTimer[i].start();
            timeDisplay[i] = new JLabel(cdt[i].toString());
            secDisplay[i] = new JLabel("Seconds: ");
            minDisplay[i] = new JLabel("Minutes: ");
            hourDisplay[i] = new JLabel("Hours: ");
            sec[i] = new JTextField(5);
            min[i] = new JTextField(5);
            hour[i] = new JTextField(5);
            start[i] = new JButton("Start");
            stop[i] = new JButton("Stop");
            set[i] = new JButton("Set");
            start[i].addActionListener(timer[i]);
            stop[i].addActionListener(timer[i]);
            set[i].addActionListener(timer[i]);
            panel[i] = new JPanel();
            panel[i].add(hourDisplay[i]);
            panel[i].add(hour[i]);
            panel[i].add(minDisplay[i]);
            panel[i].add(min[i]);
            panel[i].add(secDisplay[i]);
            panel[i].add(sec[i]);
            panel[i].add(start[i]);
            panel[i].add(stop[i]);
            panel[i].add(set[i]);
            panel[i].add(timeDisplay[i]);
            add(panel[i]);
        }
        setPreferredSize(new Dimension(750, 40 * AMOUNT));
    }

    /*******************************************************************
     * Action Listener that activates when certain buttons are pressed
     *******************************************************************/
    private class TimerListener implements ActionListener {
        /********************************************************************
         * ActionListener that is activated whenever someone pushes a button
         ********************************************************************/
        public void actionPerformed(ActionEvent e) {
            // CountDownTimer that will be compared to at zero
            CountDownTimer zero = new CountDownTimer();
            // placeholders for the text from the JTextFields
            String[] secText = new String[AMOUNT];
            String[] minText = new String[AMOUNT];
            String[] hourText = new String[AMOUNT];
            // runs through each part of the arrays and checks which button needs to be pressed
            for (int i = 0; i < AMOUNT; i++) {
                // checks if one of the start buttons is being pressed
                if (e.getSource() == start[i]){
                    go[i] = true;
                }
                // checks if one of the stop buttons is being pressed
                else if (e.getSource() == stop[i])
                    go[i] = false;
                // checks if one of the set buttons is being pressed and sets the minutes hours and seconds input
                if (e.getSource() == set[i]) {
                    secText[i] = sec[i].getText();
                    minText[i] = min[i].getText();
                    hourText[i] = hour[i].getText();
                    // if one of the boxes is blank, it will input zero
                    if (secText[i].equals("")) {
                        cdt[i].seconds = 0;
                    } else {
                        cdt[i].seconds = Integer.parseInt(secText[i]);
                    }
                    if (minText[i].equals("")) {
                        cdt[i].minutes = 0;
                    } else {
                        cdt[i].minutes = Integer.parseInt(minText[i]);
                    }
                    if (hourText[i].equals("")) {
                        cdt[i].hours = 0;
                    } else {
                        cdt[i].hours = Integer.parseInt(hourText[i]);
                    }
                    // sets timeDisplay to show the time in the countdowntimer
                    timeDisplay[i].setText(cdt[i].toString());
                    // stops the timer after setting it
                    go[i] = false;
                }
                // the timer should be counting down if the go boolean is true or the countdowntimer isn't zero
                if (go[i] == true && !cdt[i].equals(zero)) {
                    javaTimer[i].start();
                    cdt[i].dec();
                    timeDisplay[i].setText(cdt[i].toString());
                    count[i]++;
                    }
                // the timer shouldn't be counting down if the go boolean is false or the countdowntimer is zero
                if (go[i] == false || cdt[i].compareTo(zero) <= 0) {
                    javaTimer[i].stop();
                }
            }
            // for testing purposes
            System.out.println(count[0] + "\t" + count[1] + "\t" + count[2]);

        }
    }
}

1 个答案:

答案 0 :(得分:3)

问题在于您的TimerListener

基本上,正在发生的事情是,每次调用它时,它都会执行此代码块...

if (go[i] == true && !cdt[i].equals(zero)) {
    javaTimer[i].start();
    cdt[i].dec();
    timeDisplay[i].setText(cdt[i].toString());
    count[i]++;
}

这意味着,如果您有3个计数器在运行,则此代码块将每秒执行9次。每个计数器三次/ Timer

TimerListener过于笼统,并试图做太多事情。

要么创建一个“单一”Timer,它会在常规基础上打勾并根据需要更新每个计数器(这样每个循环都处理一个计数器)或修改TimerListener以便它详细了解它正在管理的柜台,并仅与该柜台交易。

更新了可能的解决方案

此示例使用单个集中式Timer,它只是在背景中打勾。根据需要,Counter会注册一个特殊的Timertick会在Counter发生时通知它。 CountDownTimer然后递减CountDownTimer并更新UI。

这是一个不完美的例子,因为我希望Counter有一个监听器接口,能够通知已注册的监听器对象的状态已经以某种方式发生了变化。这可以通过包装器import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Scanner; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class TestTimerPane { public static void main(String[] args) { new TestTimerPane(); } public TestTimerPane() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } CountDownManager countDownManager = new CountDownManager(); JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; frame.add(new TimerPane(countDownManager), gbc); frame.add(new TimerPane(countDownManager), gbc); frame.add(new TimerPane(countDownManager), gbc); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class CountDownManager { private List<Counter> timers; public CountDownManager() { timers = new ArrayList<>(25); Timer timer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Iterator<Counter> it = timers.iterator(); while (it.hasNext()) { it.next().tick(CountDownManager.this); } } }); timer.start(); } public void add(Counter timer) { timers.add(timer); } public void remove(Counter timer) { timers.remove(timer); } } public class TimerPane extends JPanel { private JTextField fldHours; private JTextField fldMins; private JTextField fldSecs; private JButton btnStart; private JButton btnStop; private JButton btnSet; private JLabel countDown; private CountDownTimer countDownTimer; private Counter counter; public TimerPane(final CountDownManager countDownManager) { fldHours = new JTextField(2); fldMins = new JTextField(2); fldSecs = new JTextField(2); btnSet = new JButton("Set"); btnStop = new JButton("Stop"); btnStart = new JButton("Start"); countDown = new JLabel("??:??:??"); add(fldHours); add(new JLabel(":")); add(fldMins); add(new JLabel(":")); add(fldSecs); add(btnSet); add(btnStart); add(btnStop); add(countDown); btnSet.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { countDownTimer = new CountDownTimer( toInt(fldHours), toInt(fldMins), toInt(fldSecs)); counter = new Counter(countDown, countDownTimer); countDown.setText(countDownTimer.toString()); } }); btnStart.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (counter != null) { countDownManager.add(counter); } } }); btnStop.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (counter != null) { countDownManager.remove(counter); } } }); } protected int toInt(JTextField field) { int value = 0; try { value = Integer.parseInt(field.getText()); } catch (NumberFormatException exp) { } return value; } } public class Counter { private JLabel output; private CountDownTimer timer; public Counter(JLabel output, CountDownTimer timer) { this.output = output; this.timer = timer; } public void tick(CountDownManager manager) { timer.dec(); output.setText(timer.toString()); if (timer.convertToSeconds() <= 0) { manager.remove(this); } } } public static class CountDownTimer { /** * Amount of hours that are being counted down in the timer */ int hours; /** * Amount of minutes that are being counted down in the timer */ int minutes; /** * Amount of seconds that are being counted down in the timer */ int seconds; /** * Boolean that determines if the add method will work. It is changed with * the toggleSuspend method */ static boolean toggle = false; /** * *************************************************************************************** * Default constructor that creates a CountDownTimer object with no time * contained in it * *************************************************************************************** */ public CountDownTimer() { hours = 0; minutes = 0; seconds = 0; } /** * ******************************************************************************************* * Constructor that uses the input amount of hours, minutes, and seconds to * count down from * * Does not allow time that is negative or allow seconds or minutes that are * over 60 * * @param hours amount of hours that will be counted down from * @param minutes amount of minutes that will be counted down from * @param seconds amount of seconds that will be counted down from * ******************************************************************************************* */ public CountDownTimer(int hours, int minutes, int seconds) { super(); // doesn't allow negative minutes, seconds, or hours if (seconds < 0 || minutes < 0 || hours < 0) { throw new IllegalArgumentException("Time cannot be negative"); } // doesn't allow seconds that are higher than 60 if (seconds >= 60) { throw new IllegalArgumentException( "Cannot have more than 60 seconds"); } // doesn't allow minutes that are higher than 60 if (minutes >= 60) { throw new IllegalArgumentException( "Cannot have more than 60 minutes"); } this.hours = hours; this.minutes = minutes; this.seconds = seconds; } /** * ******************************************************************* * Constructor that takes minutes and seconds, and sets hours to zero also * doesn't allow minutes or seconds to be negative or above 60 * * @param minutes amount of minutes that will be counted down from * @param seconds amount of seconds that will be counted down from * *********************************************************************** */ public CountDownTimer(int minutes, int seconds) { super(); // doesn't allow seconds minutes or hours to be negative if (seconds < 0 || minutes < 0 || hours < 0) { throw new IllegalArgumentException("Time cannot be negative"); } // doesn't allow seconds to be greater than 60 if (seconds >= 60) { throw new IllegalArgumentException( "Cannot have more than 60 seconds"); } // doesn't allow minutes to be greater than 60 if (minutes >= 60) { throw new IllegalArgumentException( "Cannot have more than 60 minutes"); } this.hours = 0; this.minutes = minutes; this.seconds = seconds; } /** * ********************************************************************* * Constructor that only takes seconds and sets hours and minutes to 0 does * not allow the seconds to be above 60 or negative * * @param seconds amount of seconds that will be counted down from * *********************************************************************** */ public CountDownTimer(int seconds) { super(); // doesn't allow seconds minutes or hours to be negative if (seconds < 0 || minutes < 0 || hours < 0) { throw new IllegalArgumentException("Time cannot be negative"); } // doesn't allow seconds to be greater than 60 if (seconds >= 60) { throw new IllegalArgumentException( "Cannot have more than 60 seconds"); } this.hours = 0; this.minutes = 0; this.seconds = seconds; } /** * Constructor that clones one CountDownTimer object into a new * CountDownTimer object * * @param other The CountDownTimer object that is being cloned * */ public CountDownTimer(CountDownTimer other) { this.hours = other.hours; this.minutes = other.minutes; this.seconds = other.seconds; } /** * ***************************************************************************************************************************** * Constructor that converts a string in the format of "00:00:00" into * seconds minutes and hours so it can be counted down from * * @param startTime String that is converted into seconds minutes and hours * ***************************************************************************************************************************** */ public CountDownTimer(String startTime) { // Separates the seconds minutes and hours into an array String[] parts = startTime.split(":"); // if the array has only one cell, that means only seconds were input if (parts.length == 1) { seconds = Integer.parseInt(parts[0]); } // if the array has only 2 cells that means there is only minutes and seconds input if (parts.length == 2) { minutes = Integer.parseInt(parts[0]); seconds = Integer.parseInt(parts[1]); } // if the array has 3 cells that means there is seconds minutes and hours input if (parts.length == 3) { hours = Integer.parseInt(parts[0]); minutes = Integer.parseInt(parts[1]); seconds = Integer.parseInt(parts[2]); } // doesn't allow seconds minutes or hours to be negative if (seconds < 0 || minutes < 0 || hours < 0) { throw new IllegalArgumentException("Time cannot be negative"); } // doesn't allow seconds to be greater than or equal to 60 if (seconds >= 60) { throw new IllegalArgumentException( "Cannot have more than 60 seconds"); } // doesn't allow minutes to be greater than or equal to 60 if (minutes >= 60) { throw new IllegalArgumentException( "Cannot have more than 60 minutes"); } } /** * ************************************************************************************************ * Method that returns true or false based on whether or not two * CountDownTimer objects are equal * * @param other Object that is being compared to another CountDownTimer * ************************************************************************************************ */ public boolean equals(Object other) { // converts the two objects to seconds then compares them if (this.convertToSeconds() == ((CountDownTimer) other) .convertToSeconds()) { return true; } return false; } /** * ****************************************************************************** * Returns a boolean based on whether two CountDownTimers, t1 and t2, are * equal * * @param t1 first CountDownTimer being compared * @param t2 second CountDownTimer being compared * ****************************************************************************** */ public static boolean equals(CountDownTimer t1, CountDownTimer t2) { // converts the two objects to seconds and then compares them if (t1.convertToSeconds() == t2.convertToSeconds()) { return true; } return false; } /** * ********************************************************************************************** * Compares to CountDownTimer objects and returns an int 1, 0, or -1 based * on whether the first object is greater than, equal to, or less than the * CountDownTimer in the parameter * * @param other CountDownTimer that is being compared * *********************************************************************************************** */ public int compareTo(CountDownTimer other) { if (this.convertToSeconds() > other.convertToSeconds()) { return 1; } else if (this.convertToSeconds() < other.convertToSeconds()) { return -1; } return 0; } /** * ************************************************************************************************ * Compares to CountDownTimer objects and returns an int 1, 0, or -1 based * on whether the first object (t1) is greater than, equal to, or less than * the second object (t2) * * @param t1 first object being compared * @param t2 second object being compared * @return * ************************************************************************************************* */ public static int compareTo(CountDownTimer t1, CountDownTimer t2) { if (t1.convertToSeconds() > t2.convertToSeconds()) { return 1; } else if (t1.convertToSeconds() < t2.convertToSeconds()) { return -1; } return 0; } /** * ************************************************************* * subtracts the input amount of seconds from a CountDownTimer * * @param seconds amount of seconds the user wants to subtract * ************************************************************* */ public void subtract(int seconds) { // places the amount of seconds into an integer int tempSeconds = this.convertToSeconds(); // subtracts the input seconds from the seconds that were converted tempSeconds -= seconds; // converts the new seconds back into the object formatSeconds(tempSeconds); } /** * ***************************************************************************************** * Subtracts the amount of time contained in one CountDownTimer from another * CountDownTimer * * @param other CountDownTimer that is doing the subtracting * ***************************************************************************************** */ public void subtract(CountDownTimer other) { int otherSeconds = other.convertToSeconds(); this.subtract(otherSeconds); } /** * ********************************************************************* * Adds seconds to the object based on what is put into the parameter * * @param seconds amount of seconds being added to the CountDownTimer * ********************************************************************** */ public void add(int seconds) { // keeps the method from adding when the toggle is activated if (toggle == false) { int tempSeconds = this.convertToSeconds(); tempSeconds += seconds; formatSeconds(tempSeconds); } else { throw new IllegalArgumentException( "Cannot use add when toggle is enabled"); } } /** * Adds the seconds from one CountDownTimer to another CountDownTimer * * @param other CountDownTimer that is being added to another CountDowntimer */ public void add(CountDownTimer other) { // doesn't allow the method to add when the toggle is true if (toggle == false) { int otherSeconds = other.convertToSeconds(); this.add(otherSeconds); } else { throw new IllegalArgumentException( "Cannot use add when toggle is enabled"); } } /** * ***************************************** * Decreases the CountDownTimer by 1 second * ***************************************** */ public void dec() { int tempSeconds = this.convertToSeconds(); tempSeconds--; formatSeconds(tempSeconds); } /** * ************************************************** * Increases the CountDownTimer object by 1 second * ************************************************* */ public void inc() { int tempSeconds = this.convertToSeconds(); tempSeconds--; formatSeconds(tempSeconds); } /** * Returns the object as a string in the format of "00:00:00" */ public String toString() { String time = "" + this.hours + ":"; if (this.minutes < 10) { time += "0" + this.minutes + ":"; } else { time += this.minutes + ":"; } if (this.seconds < 10) { time += "0" + this.seconds; } else { time += this.seconds; } return time; } /** * ********************************************** * Saves the object with a specified name * * @param fileName name of the file being saved * *********************************************** */ public void save(String fileName) { PrintWriter out = null; try { out = new PrintWriter(new BufferedWriter(new FileWriter(fileName))); } catch (IOException e) { e.printStackTrace(); } out.println(this.hours); out.println(this.minutes); out.println(this.seconds); out.close(); } /** * ************************************************ * Loads the object with the specified name * * @param fileName Name of the file being loaded * ************************************************ */ public void load(String fileName) { try { Scanner fileReader = new Scanner(new File(fileName)); this.hours = fileReader.nextInt(); this.minutes = fileReader.nextInt(); this.seconds = fileReader.nextInt(); fileReader.close(); System.out.println("Hours: " + this.hours); System.out.println("Minutes: " + this.minutes); System.out.println("Seconds: " + this.seconds); } catch (FileNotFoundException error) { System.out.println("File not found"); } catch (IOException error) { System.out.println("OH NO THAT WAS NOT SUPPOSED TO HAPPEN"); } } /** * ******************************************************************************************** * Switches the toggle boolean, and doesn't allow the add methods to work * when it is activated * ********************************************************************************************** */ public static void toggleSuspend() { if (toggle == false) { toggle = true; } if (toggle == true) { toggle = false; } } /** * ********************************************************************************* * Formats a certain amount of seconds and puts it into an existing * CountDownTimer * * @param seconds seconds being formatted * ********************************************************************************* */ private void formatSeconds(int seconds) { this.hours = seconds / 3600; seconds %= 3600; this.minutes = seconds / 60; this.seconds = seconds % 60; } /** * *************************************************************************** * Returns the amount of seconds that are contained in a CountDownTime * object * *************************************************************************** */ private int convertToSeconds() { int hSeconds = hours * 3600; int mSeconds = minutes * 60; return hSeconds + mSeconds + seconds; } } } 类来实现,但我要懒惰。

Timer

Timer

现在,如果你需要一个单独的CountDownTimerCountDownTimer,那么我可能会创建某种“工人”类,它将采用Timer并且具有自包含{ {1}}。我还会提供一些有兴趣的人可以注册的听众,并允许他们按照自己的意愿更新用户界面......