Reputation: 1
My program is pretty simple - it generates a random number and then increments an array at that index, essentially tallying how often it comes up, which is displayed in a bar graph type JPanel. It does this every "updateInterval" milliseconds, 50 by default. I'm trying to, upon user input, change this interval. My initial code was this:
Timer t = new Timer();
GenerateNumberTask genTask = new GenerateNumberTask(); //extends TimerTask
public void startTimer(){
t.scheduleAtFixedRate(genTask, 0, updateInterval);
}
For obvious reasons, changing 'updateInterval' doesn't change the used interval once it has begun. I had thought that calling this next code afterwards in the needed area (the button ActionListener it's being changed from) would update the timer with the new interval, but it doesn't.
t.purge();
genTask = new GenerateNumberTask();
t.startTimer();
Afterwards, I looked into ScheduledExecutorService, but that just confused me more.
It seems like the next thing would be to make a new Thread(), run the task as a Runnable and just Thread.sleep the interval.
What's the correct way of going at this?
EDIT: At the suggestion of @MadProgrammer, I've changed it to a swing timer, yet the problem still stands.
public void startTimer(){
t = new Timer(timeBetweenUpdates, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//irrelevant code
}
});
t.start();
}
later, in the actionlistener
//timeBetweenUpdates changes before this line
t.setDelay(timeBetweenUpdates);
Still, the result it the same.
EDIT 2: Solved it. I accidentally called the startTimer() in both the constructor and main method.
Upvotes: 0
Views: 235
Reputation: 347194
You should be using a Swing (javax.swing
) Timer
, this will set up a regular callback which is executed with the context of the Event Dispatching Thread, making it safe to update the UI from within.
See Concurrency in Swing and How to use Swing Timers for more details
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestTimer {
public static void main(String[] args) {
new TestTimer();
}
public TestTimer() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane testPane = new TestPane();
Timer timer = new Timer(10, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
testPane.repaint();
}
});
JSlider slider = new JSlider(10, 1000);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
timer.setDelay(slider.getValue());
}
});
slider.setValue(10);
timer.start();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(testPane);
frame.add(slider, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private long lastUpdate = -1;
public TestPane() {
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
String text = "...";
if (lastUpdate > 0) {
long duration = System.currentTimeMillis() - lastUpdate;
text = Long.toString(duration);
}
FontMetrics fm = g2d.getFontMetrics();
int x = (getWidth() - fm.stringWidth(text)) / 2;
int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
g2d.drawString(text, x, y);
lastUpdate = System.currentTimeMillis();
g2d.dispose();
}
}
}
Upvotes: 1