问题
I have an application that I want to refresh screen in some periods.User will select a task in combo, if job is active task, a timer will be started.So only one timer exists.
I am trying to stop timer when a new task is selected from combo.Here is stop timer function. It seems it does not work for some cases.But I could not catch the case. Although timer is not null and is Running, it does not stop.it works at the begining of program, after a while does not work.
public void stopTimer() {
logger.error("Timer is ready to stop: ");
if (notifierTimer != null) {
logger.error("Coalesce: " + notifierTimer.isCoalesce());
logger.error("Running: " + notifierTimer.isRunning());
}
if (notifierTimer != null && notifierTimer.isRunning()) {
notifierTimer.stop();
logger.error("Timer stopped for job id");
}
}
public void setTimer(final long jobId) {
final int timerTriggerTime = 10000;
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
graph.trigger(jobId);
logger.error("Graph Triggered: " + jobId);
}
};
/** create Timer */
notifierTimer = new Timer(timerTriggerTime, listener);
/** start timer */
notifierTimer.start();
/** run timer for each user specifed time */
notifierTimer.setDelay(timerTriggerTime);
logger.error("Timer started for job id" + jobId);
}
回答1:
This one is for both the OP and for Perry Monschau: This is an example of a "working" Swing Timer, one that starts and stops on command. I'm not yet done with this program as I'm trying to make it more MVC-like, but nevertheless run it and you'll see it functions fine.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class CountDownTimer extends JPanel {
private static final int BL_GAP = 5;
private static final int MS_PER_SEC = 1000;
private static final int SEC_PER_MIN = 60;
private static final int MIN_PER_HR = 60;
private static final float DISPLAY_PTS = 54f;
private static final String DISPLAY_FORMAT_STR = "%02d:%02d:%02d:%01d";
private static final float SPINNER_FONT_PTS = 16f;
public static final int TIMER_DELAY = 50;
public static final Color NEGATIVE_COLOR = Color.red;
private StartAction startAction = new StartAction();
private ResetAction resetAction = new ResetAction(startAction);
private QuitAction quitAction = new QuitAction();
private final Action[] btnActions = { resetAction , startAction ,
quitAction };
private JSpinner hourSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10,
1));
private JSpinner minuteSpinner = new JSpinner(new SpinnerNumberModel(0, 0,
60, 1));
private JSpinner secondSpinner = new JSpinner(new SpinnerNumberModel(0, 0,
60, 1));
private JLabel displayField = new JLabel("", SwingConstants.CENTER);
private long startTime;
private long currentTime;
private long deltaTime;
private long setTimeToComplete;
private boolean negative = false;
private Timer timer;
private int hours;
private int min;
private int sec;
private int msec;
private JFrame frame;
public CountDownTimer(JFrame frame) {
this.frame = frame;
displayField.setFont(displayField.getFont().deriveFont(Font.BOLD,
DISPLAY_PTS));
displayField.setBorder(BorderFactory.createLineBorder(Color.blue, 2));
setLayout(new BorderLayout(BL_GAP, BL_GAP));
int eb = 2;
setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
add(displayField, BorderLayout.NORTH);
add(createGuiBody());
showTimeLeft();
}
private JPanel createGuiBody() {
JPanel bodyPanel = new JPanel();
bodyPanel.setLayout(new BoxLayout(bodyPanel, BoxLayout.PAGE_AXIS));
bodyPanel.add(createSpinnerPanel());
bodyPanel.add(createButtonPanel());
return bodyPanel;
}
private JPanel createButtonPanel() {
JPanel innerBtnPanel = new JPanel(new GridLayout(1, 0, BL_GAP, 0));
for (Action action : btnActions) {
innerBtnPanel.add(new JButton(action));
}
JPanel btnPanel = new JPanel(new BorderLayout());
btnPanel.add(innerBtnPanel);
return btnPanel;
}
private JPanel createSpinnerPanel() {
Font font = hourSpinner.getFont().deriveFont(Font.BOLD, SPINNER_FONT_PTS);
hourSpinner.setFont(font);
minuteSpinner.setFont(font);
secondSpinner.setFont(font);
JPanel spinnerPanel = new JPanel();
spinnerPanel.add(new JLabel("Hrs:"));
spinnerPanel.add(hourSpinner);
spinnerPanel.add(Box.createHorizontalStrut(BL_GAP * 2));
spinnerPanel.add(new JLabel("Min:"));
spinnerPanel.add(minuteSpinner);
spinnerPanel.add(Box.createHorizontalStrut(BL_GAP * 2));
spinnerPanel.add(new JLabel("Secs:"));
spinnerPanel.add(secondSpinner);
return spinnerPanel;
}
private void showTimeLeft() {
int oldMin = min;
hours = (int) (deltaTime / (MS_PER_SEC * SEC_PER_MIN * MIN_PER_HR));
min = (int) (deltaTime / (MS_PER_SEC * SEC_PER_MIN) % MIN_PER_HR);
sec = (int) (deltaTime / (MS_PER_SEC) % SEC_PER_MIN);
msec = (int) (deltaTime % MS_PER_SEC);
String displayString = String.format(DISPLAY_FORMAT_STR, hours, min, sec,
msec / 100);
displayField.setText(displayString);
if (Math.abs(oldMin - min) > 0) {
String title = frame.getTitle().replaceAll("\\d", "");
title = String.format("%02d " + title, min);
frame.setTitle(title);
}
}
private class ResetAction extends AbstractAction {
private StartAction startAction;
public ResetAction(StartAction startAction) {
super("Reset");
putValue(MNEMONIC_KEY, KeyEvent.VK_R);
this.startAction = startAction;
}
public void actionPerformed(ActionEvent evt) {
if (startAction != null
&& startAction.getValue(NAME).equals(StartAction.STOP)) {
startAction.actionPerformed(new ActionEvent(evt.getSource(),
ActionEvent.ACTION_PERFORMED, StartAction.STOP));
} else if (timer != null && timer.isRunning()) {
timer.stop();
}
displayField.setForeground(null);
deltaTime = (Integer) hourSpinner.getValue();
deltaTime = MIN_PER_HR * deltaTime
+ (Integer) minuteSpinner.getValue();
deltaTime = SEC_PER_MIN * deltaTime
+ (Integer) secondSpinner.getValue();
deltaTime = MS_PER_SEC * deltaTime;
showTimeLeft();
negative = false;
timer = new Timer(TIMER_DELAY, new TimerListener());
}
}
private class StartAction extends AbstractAction {
public static final String START = "Start";
public static final String STOP = "Stop";
public StartAction() {
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
putValue(NAME, START);
}
public void actionPerformed(ActionEvent evt) {
if (timer == null) {
return;
}
if (getValue(NAME).equals(START)) {
putValue(NAME, STOP);
startTime = System.currentTimeMillis();
currentTime = startTime;
setTimeToComplete = deltaTime;
timer.start();
} else {
if (timer != null && timer.isRunning()) {
putValue(NAME, START);
timer.stop();
}
}
}
}
private class QuitAction extends AbstractAction {
public QuitAction() {
super("Quit");
putValue(MNEMONIC_KEY, KeyEvent.VK_Q);
}
public void actionPerformed(ActionEvent arg0) {
if (timer != null && timer.isRunning()) {
timer.stop();
}
frame.dispose();
}
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
currentTime = System.currentTimeMillis();
deltaTime = setTimeToComplete - currentTime + startTime;
if (deltaTime < 0) {
deltaTime = -deltaTime;
if (!negative) {
negative = true;
displayField.setForeground(NEGATIVE_COLOR);
}
}
showTimeLeft();
}
}
private static void createAndShowGui() {
String title = "Count Down Timer";
title = JOptionPane.showInputDialog("Timer Title?", title);
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CountDownTimer(frame));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
回答2:
Can you just use one Timer and add/remove listeners as needed? Does this type of thing work for you?
class Example {
// try using one timer.
Timer timer = new Timer(1000, null); // initial
// don't know if you only call these methods
// inside the Swing thread. If you do, you can
// remove synchronized.
public synchronized void startRefresh(int jobId) {
// just to make sure nothing is running...
stopRefresh();
int triggerTime = 1000;
ActionListener listener = ...;
timer.setDelay(triggerTime);
timer.setInitialDelay(triggerTime);
timer.addActionListener(listener);
timer.start();
}
public synchronized void stopRefresh() {
timer.stop();
for (ActionListener listener : timer.getActionListeners()) {
timer.removeActionListener(listener);
}
}
}
回答3:
Yeah I don't use Timer for reasons such as being buggy like that.
public class MyTimer extends Thread {
boolean kill = false;
int tick = 10;
ActionListener al;
public MyTimer(int tick, ActionListener al) {
this.tick = tick;
this.al = al;
}
public void run() {
try {
while(!kill) {
al.actionPerformed(new ActionEvent(this,ActionEvent.ACTION_PERFORMED,"tick"));
Thread.sleep(tick);
}
} catch (InterruptedException e) {
}
}
public void stop()
{
kill = true;
}
}
Should work...
来源:https://stackoverflow.com/questions/9759115/enable-to-stop-timer