How to work with Swing timer - java

I'm trying to stop the program for a second using Swing Timer.
Timer timer = new Timer(10000,
new ActionListener(public void actionPerformed(ActionEvent e) {}));
didn't work
public class Card extends JButton implements ActionListener {
int numberClick = 0;
public card() {
addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
numberClick++;
if(numberClick == 2) {
Timer timer = new Timer(10000, );
timer.start();
numberClick = 0;
}
}
}

You seem to lack basic understanding of how the Timer works. Please read How to Use Swing Timers. The concept is fairly simple.
The first argument in the Timer constructor is the delay. Seems you have that part down. The second argument is the ActionListener that listens for the "Timer Events" (actually ActionEvents). An event is fired each delayed time. The callback (actionPerformed) contains what should be performed after that delay (tick). So whatever you want to happen after that second, put it in the actionPerformed of the timer's ActionListener.
Also if you only want it t occur once, you should call timer.setRepeats(false);. Also note, you are using 10000, which is in milliseconds, so it's 10 seconds, not 1. You should change it to 1000
Example Flow
JButton button = new JButton("Press Me");
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
Timer timer = new Timer(1000, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Print after one second");
}
});
timer.setRepeats(false);
timer.start();
}
});
Press Button → Wait One Second → Print Statement

Related

Manually invoke actionPerformed of a javax.swing.Timer

The following Timer works perfectly.
private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// ...
}
});
What I want to do is call the actionPerformed() manually. How can I achieve this?
The question seems unclear to the readers, I'll try to explain more.
Timer does some process hourly. I want to do it whenever I want without interfering the timer's process.
Short answer...
A much simpler (and better designed) solution would be, instead of...
private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("OK");
}
});
You should externalise the work the ActionListener does...
private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
doReallyImportantWorkEveryHour();
}
});
then you remove the Timer from the equation and you can call doReallyImportantWorkEveryHour when you want and solve the fundamental problem
Long Answer
So, let's start with...
private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("OK");
}
});
Creating a Timer this way, automatically registers a ActionListener with the Timer.
You then state:
What I want to do is call the actionPerformed() method inside the timer's ActionListener manually. How can I achieve this?
Which suggest you want try and do something like...
private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
TICK_HOUR.getActionListeners()[0].actionPerformed(null);
}
});
This could cause a NullPointerException, but more importantly, this will have an adverse affect on system performance, as there is no way that the ActionListener will know it shouldn't continuously all itself - basically and infinite loop.
IF however, you wanted to, prematurely, trigger the Timers ActionListeners (outside of any registered listeners)
Then yes, you could use...
ActionEvent evt = new ActionEvent(
TICK_HOUR,
0,
TICK_HOUR.getActionCommand(),
System.currentTimeMillis(),
0);
for (ActionListener listener : TICK_HOUR.getActionListeners()) {
listener.actionPerformed(evt);
}
but make sure you're calling them from within the context of the EDT, as that's one of the guarantees that the Timer makes.
A "simpler" solution might be just to use the functionality that is already provide by the Timer itself...
public class ManuallyTimer extends Timer {
public ManuallyTimer(int delay, ActionListener listener) {
super(delay, listener);
}
public void tigger() {
ActionEvent evt = new ActionEvent(TICK_HOUR, 0, TICK_HOUR.getActionCommand());
fireActionPerformed(new ActionEvent(this, 0, getActionCommand(),
System.currentTimeMillis(),
0));
}
}
Inside a static-initializer-block store ActionListener in a variable instead of passing it directly to the Timer:
private static final Timer TICK_HOUR;
static{
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// ...
}
};
TICK_HOUR = = new Timer(3600000, listener);
listener.actionPerformed(/* someEvent */);
}
You might aswell store the listener variable as a class level static variable and then call it elsewhere from your code:
private static final ActionListener LISTENER = new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// ...
}
};
private static final Timer TICK_HOUR = new Timer(3600000, LISTENER);
And then somewhere in your code
LISTENER.actionPerformed(/* someEvent */);
Use getActionListeners().
Returns an array of all the action listeners registered on this timer.
Returns:
all of the timer's ActionListeners or an empty array if no action listeners are currently registered.
~Java doc~
TICK_HOUR.getActionListeners()[0].actionPerformed(null);
This will throw a ArrayIndexOutOfBoundsException if there are no ActionListeners registered to the timer. So better check the length of the array before using.

Timer works with println but not label using java

I have some labels that become visible when the letter a is pressed.
private void formKeyPressed(java.awt.event.KeyEvent evt) {
// TODO add your handling code here:
if(evt.getKeyCode()==KeyEvent.VK_A){
jLabel7.setVisible(true);
jLabel8.setVisible(true);
jLabel9.setVisible(true);
myBlink();
}
I have Label8 on a timer myBlink()
public void myBlink()
{
new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("begin");
jLabel8.setVisible(false);
jLabel8.setVisible(true);
System.out.println("Timer");
}
}).start();
}
I have placed printlns to see if timer begins and ends and when I press key "a" my output shows begin Timer multiple times but my label does not appear and disappear. What tweak does this code need? What am I missing? Thanks for the extra set of eyes.
This is probably because you call successively setVisible(false) and setVisible(true) which is done too fast to be seen, you should use a variable and modify its value any time the action of the Timer is called as next:
public void myBlink()
{
new Timer(1000, new ActionListener() {
boolean visible = true;
public void actionPerformed(ActionEvent e) {
jLabel8.setVisible(visible = !visible);
}
}).start();
}

How to add a delay to my JTable?

I need a delay in my JTable every time a row is added.
public void añadirNuevo(Procesos procesosArray){
for(int i=0;i<procesosArray.size();i++){
Object nuevo[]= {procesosArray.obtener(i).getNombre(),procesosArray.obtener(i).getTam()};
nuevoTbl.addRow(nuevo);
//DELAY
}
}
Use javax.swing.Timer
Setting up a timer involves creating a Timer object, registering one
or more action listeners on it, and starting the timer using the start
method. For example, the following code creates and starts a timer
that fires an action event once per second (as specified by the first
argument to the Timer constructor). The second argument to the Timer
constructor specifies a listener to receive the timer's action events.
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
new Timer(delay, taskPerformer).start();
You can use Thread.sleep method
public void añadirNuevo(Procesos procesosArray){
for(int i=0;i<procesosArray.size();i++){
Object nuevo[]= {procesosArray.obtener(i).getNombre(),procesosArray.obtener(i).getTam()};
nuevoTbl.addRow(nuevo);
try {
Thread.sleep(1000); // 1 second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}

Java gui countdown

I need to make a GUI where a worker enters a station (a spot on the panel) and stays there for a set amount of seconds, shown in a countdown about the workers head (so, once the workers moves to the spot, the station's label shows 3s -> 2s -> 1s and then the worker leaves, and the label reverts back to "OPEN"). I'm having trouble with making this happen, as I'm not too good with the Timer(s?) that Java has. I tried with something like this:
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
//change label text/color, decrement countdown
panel.repaint();
Thread.sleep(1000);
}
});
But I can't reach the number of seconds to count down from from inside the timer, and I'm not sure how to pass that value to the timer. If someone can help me out, I'd really appreciate it.
Get rid of the Thread.sleep(). That's what the 1000 in Timer(1000, new ActionListener() does. It sets an interval for each timer event. Every time a timer event is fired, the actionPerformed is called. So you need to determine what needs to happen every "tick", and put that code in the actionPerformed. Maybe something like
Timer timer = new Timer(1000, new ActionListener() {
private int count = 5;
#Override
public void actionPerformed(ActionEvent e) {
if (count <= 0) {
label.setText("OPEN");
((Timer)e.getSource()).stop();
count = 5;
} else {
label.setText(Integer.toString(count);
count--;
}
}
});
You need to decide when to call timer.start().
For general information, see How to Use Swing Timers
Problem #1: You are calling Thread.sleep() from within the Swing GUI thread. That causes the thread to stop taking input and freeze. Delete that line. It does you no good! While you are at it, delete the repaint call as well.
Now that that's said and done, instead of creating an anonymous instance of ActionListener, you can create an actual class that implements ActionListener and provides a constructor. That constructor can have as an argument the number of seconds you want to start counting down. You can declare that class inside the method you are using, or you can declare it inside the class.
Here's a skeletal example:
public class OuterClass {
JLabel secondsLabel = ...;
Timer myTimer;
private void setupTimer(int numSecondsToCountDown) {
secondsLabel.setText(Integer.toString(numSecondsToCountDown));
myTimer = new Timer(1000, new CountdownListener(numSecondsToCountDown));
myTimer.start();
}
// ...
class CountdownListener implements ActionListener {
private int secondsCount;
public CountdownListener(int startingSeconds) { secondsCount = startingSeconds; }
public void actionPerformed(ActionEvent evt) {
secondsLabel.setText(Integer.toString(secondsCount);
secondsCount--;
if (secondsCount <= 0) { // stop the countdown
myTimer.stop();
}
}
}
}

Thread.sleep() to swing Timer conversion

I am trying to implement a Thread.sleep(6000) line but it seems to freeze in the applet. When I tried to use Timers, I wasn't sure how to use because I am not very good with event listeners. I am basically trying to call a method fetchUrl() every 6 seconds, after the user clicks the enter button. How can I implement this?
public void init() {
c = getContentPane();
c.setLayout(flow);
c.setBackground(forum);
question.setForeground(Color.white);
question.setFont(tnr);
question2.setForeground(Color.white);
question2.setFont(tnr);
result.setForeground(Color.white);
result.setFont(tnr);
resp.setBorder(BorderFactory.createBevelBorder(0));
timeLength.setBorder(BorderFactory.createBevelBorder(0));
c.add(question);
c.add(resp);
c.add(question2);
c.add(timeLength);
c.add(enter);
c.add(result);
resp.requestFocus();
enter.addActionListener(this);
t = new Timer(DELAY, this);
t.setInitialDelay(DELAY);
}
public void actionPerformed(ActionEvent e) {
final String n1;
int timeMin, timeSec, count = 0, maxCount;
timeMin = Integer.parseInt(timeLength.getText());
timeSec = timeMin * 60;
maxCount = (int)(timeSec/6);
if (e.getSource() == enter) { //user clicks enter
n1 = resp.getText();
while (count < maxCount) {
fetchUrl(n1); //this method called every 6 seconds
t.start();
count++;
}
}
}
First I would start by separating the ActionListener for the Timer and for the JButton.
Second nothing is happening logically with the Timer because you're swallowing it with the button source check.
Third you should understand how the timer works. Basically for every "tick" (in your case six seconds) the actionPerformed of the timer ActionListener is called. So if you want the fetch() method called, then that's what you should be visible/accessible to the in the Timer's actionPerformed.
The button's ActionListener should only handle the starting of the timer I believe. So just separate the listeners. Give each one an anonymous ActionListener and no need to make the class implement ActionListener.
For example
timer = new Timer(DELAY, new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do some stuff every six seconds
fetchURL();
}
});
enter = new JButton(...);
enter.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
If you want some automatic stopping feature for the timer, you could do something like
timer = new Timer(DELAY, new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (someStoppingCondition()) {
timer.stop();
} else {
// do some stuff every six seconds
fetchURL();
}
// do some stuff every six second
}
});
You need to call a method after user clicks on button every 6 seconds, but you have not said how many times you want to call it.
For infinite number of times, try something like the following,
while(true){
new Thread(){
#Override
public void run(){
try{
Thread.sleep(6000);
fetchUrl(n1);
}catch(InterruptedException e){}
}
}.start();
}
If you will use Thread.sleep() in your applet, then your applet will be hanged for 6 seconds and so create a new thread for it.

Categories

Resources