Java swing countdown timer not working properly - java

I would like to make a program that shuts down the computer after specific time, but I have troubles making the timer countdown. It must decrement the time in the spinners from which it takes it. I tried to make a dynamic dialog application but it doesn't work.
I apply the whole code if that is not enough.
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//decrements the amount of seconds and the time in the spinners
m_secs--;
ShutDownDialog.this.AmountOfTime--;
if (m_secs<0) {
m_secs=59;
m_mins--;
if (m_mins<0) {
m_mins=59;
m_hours--;
if(m_hours<0)
m_hours=0;
}
hours.setValue((Integer)m_hours);
minutes.setValue((Integer)m_mins);
seconds.setValue((Integer)m_secs);
label_2.setText(ShutDownDialog.
this.AmountOfTime.toString());
}
if (ShutDownDialog.this.AmountOfTime< 0)
{
timer.stop();
label_2.setText("stop"); //just to check what happens
}
}
});
StartCountdown.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
hours.setEnabled(false);
minutes.setEnabled(false);
seconds.setEnabled(false);
StartCountdown.setEnabled(false);
StopCount.setEnabled(true);
//calculates the amount of seconds and starts the timer
m_hours = ((Integer)hours.getValue()*3600); //get the hours
m_mins = ((Integer)minutes.getValue()*60); //get the minutes
m_secs = (Integer)seconds.getValue(); //get seconds
AmountOfTime = m_hours + m_mins + m_secs;
timer.start();
//JOptionPane.showMessageDialog(null, AmountOfTime);
}
});

You are updating the values only, if m_secs < 0.
Move
hours.setValue((Integer) m_hours);
minutes.setValue((Integer) m_mins);
seconds.setValue((Integer) m_secs);
outside of the if-block and it will update the labels.
It should now look like this:
private void initialize() {
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
m_secs--;
ShutDownDialog.this.AmountOfTime--;
if (m_secs<0) {
m_secs=59;
m_mins--;
if (m_mins<0) {
m_mins=59;
m_hours--;
if(m_hours<0)
m_hours=0;
}
}
hours.setValue((Integer) m_hours);
minutes.setValue((Integer) m_mins);
seconds.setValue((Integer) m_secs);
label_2.setText(ShutDownDialog.this.AmountOfTime.toString());
if (ShutDownDialog.this.AmountOfTime< 0)
{
timer.stop();
label_2.setText("stop");
}
}
});

Related

Timer doesn't work when another button is pressed (applet)

I'm making an applet which has two buttons: step back and step forward.
I have the same timer in every button to execute an animation. If I push step forward it works fine, and the animation runs, but if i push step back, the animation doesn't run or is bad runned (in a wrong position and velocity).
I guess the problem is the timer doesn't stop correctly and is running when start the timer again, but I donĀ“t know how to solve it.
This is the code of the step forward button:
//Code of the button "Paso a Paso"
this.botonPasoAPaso = new JButton("Paso a paso");
this.botonPasoAPaso.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//Avoid timer to accelerate
if (timer != null && timer.isRunning()) {
timer.stop();
}
//Code of the timer, makes an animation
timer = new Timer(35, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (pasoAPaso <= listaPaquetes.size()) {
Paquete p = listaPaquetes.get(pasoAPaso);
p.animar();
panelGrafo.removeAll();
panelGrafo.updateUI();
panelGrafo.setPaquete(p);
panelGrafo.setAnimar(true);
panelGrafo.repaint();
}
}
});
timer.start();
pasoAPaso++;
}
});
This is the code of the step back button:
this.botonAtras.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (timer != null && timer.isRunning()) {
timer.stop();
}
timer = new Timer(35, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (pasoAPaso < listaPaquetes.size() && pasoAPaso>=0) {
Paquete p = listaPaquetes.get(pasoAPaso);
p.animar();
panelGrafo.removeAll();
panelGrafo.updateUI();
panelGrafo.setPaquete(p);
panelGrafo.setPasoAPaso(pasoAPaso);
panelGrafo.setAnimar(true);
panelGrafo.repaint();
//Actualizar matriz del render para pintar celdas
RenderTabla.matrizTotal = new Cuadrado[pasos.get(pasoAPaso).length][pasos.get(pasoAPaso)[0].length];
RenderTabla.matrizTotal = pasos.get(pasoAPaso);
tabla.introducirDatos(pasos.get(pasoAPaso),false);
}
}
});
timer.start();
pasoAPaso--;
}
});
This is a video of the applet to see what's happening
If you see the video, when I click the "Paso a Paso" (Step forward) button, a truck is animated, but when I click the "rewind" (Step back) button, it doesn't work (appears a truck but is not correctly animated), and if i click again nothing happens.
Thanks.

How to implement timer to make text visible for a certain time and then replace it with another text in Java?

I am creating a mobile phone keypad. I used an array to create buttons.
For one of my buttons, I want "Dialling..." to appear on the JTextField for about 2 seconds on the click and then replace it with "No Signal" for about 2 more seconds and then clear the JTextField.
All this should be done by just 1 click. I know it is to do with timers but I can't seem to implement it.
I have something like this at the moment but it doesn't seem to be working.
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand() == "Dial")
{
timer.start();
counter++;
if(counter ==1)
{
text1.setText("Dialling . . .");
counter = 0;
}
if(e.getsource() == timer)
{
text1.setText("No Signal");
timer.stop();
}
}
Try this
public void actionPerformed(ActionEvent e) {
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand() == "Dial")
{
text1.setText("Dialling . . .");
}
}
};
Timer timer = new Timer(1000, taskPerformer); // delay one sec
timer.setRepeats(false);
timer.start();
text1.setText("No Signal");
}

Java : detect triple-click without firing double-click

I have a JTable in which I want to call a function when a cell is double-clicked and call another function when the cell is triple-clicked.
When the cell is triple-clicked I do not want to call the double-click-function.
What I have right now is (mgrdAlarm is the JTable) :
mgrdAlarm.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println("getClickCount() = " + e.getClickCount());
if (e.getClickCount()==2)
{
doubleClick();
System.out.println("Completed : doubleClick()");
}
if (e.getClickCount()==3)
{
tripleClick();
System.out.println("Completed : tripleClick()");
}
}
});
When double-clicked the console shows :
getClickCount() = 1
getClickCount() = 2
Completed : doubleClick()
When triple-clicked the console shows :
getClickCount() = 1
getClickCount() = 2
Completed : doubleClick()
getClickCount() = 3
Completed : tripleClick()
When triple-clicked I want the console to show :
getClickCount() = 1
getClickCount() = 2
getClickCount() = 3
Completed : tripleClick()
So I do not want to call the function doubleClick() when the cell is triple-clicked, but I do want to call the function doubleClick() when the cell is double-clicked.
[EDIT]
As all replies suggest the solution seems to be to delay the double-click-action and wait a certain time for the triple-click.
But as discussed here that might lead to a different type of problem :
The user might have set his double-click-time quite long, which might overlap with the timeout of my triple-click.
It is no real disaster if my double-click-action is executed before my triple-click-action, but it does generate some extra overhead, and especially some extra data traffic which I would like to prevent.
As the only solution so far might lead to other problems, which might actually be worse than the original problem, I will leave it as it is right now.
public class TestMouseListener implements MouseListener {
private boolean leftClick;
private int clickCount;
private boolean doubleClick;
private boolean tripleClick;
public void mouseClicked(MouseEvent evt) {
if (evt.getButton()==MouseEvent.BUTTON1){
leftClick = true; clickCount = 0;
if(evt.getClickCount() == 2) doubleClick=true;
if(evt.getClickCount() == 3){
doubleClick = false;
tripleClick = true;
}
Integer timerinterval = (Integer)Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
Timer timer = new Timer(timerinterval, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(doubleClick){
System.out.println("double click.");
clickCount++;
if(clickCount == 2){
doubleClick(); //your doubleClick method
clickCount=0;
doubleClick = false;
leftClick = false;
}
}else if (tripleClick) {
System.out.println("Triple Click.");
clickCount++;
if(clickCount == 3) {
tripleClick(); //your tripleClick method
clickCount=0;
tripleClick = false;
leftClick = false;
}
} else if(leftClick) {
System.out.println("single click.");
leftClick = false;
}
}
});
timer.setRepeats(false);
timer.start();
if(evt.getID()==MouseEvent.MOUSE_RELEASED) timer.stop();
}
}
public static void main(String[] argv) throws Exception {
JTextField component = new JTextField();
component.addMouseListener(new TestMouseListener());
JFrame f = new JFrame();
f.add(component);
f.setSize(300, 300);
f.setVisible(true);
component.addMouseListener(new TestMouseListener());
}
}
The previous answers are correct: you have to account for the timing and delay recognizing it as a double click until a certain amount of time has passed. The challenge is that, as you have noticed, the user could have a very long or very short double click threshold. So you need to know what the user's setting is. This other Stack Overflow thread ( Distinguish between a single click and a double click in Java ) mentions the awt.multiClickInterval desktop property. Try using that for your threshold.
You can do something like that, varying delay time:
public class ClickForm extends JFrame {
final static long CLICK_FREQUENTY = 300;
static class ClickProcessor implements Runnable {
Callable<Void> eventProcessor;
ClickProcessor(Callable<Void> eventProcessor) {
this.eventProcessor = eventProcessor;
}
#Override
public void run() {
try {
Thread.sleep(CLICK_FREQUENTY);
eventProcessor.call();
} catch (InterruptedException e) {
// do nothing
} catch (Exception e) {
// do logging
}
}
}
public static void main(String[] args) {
ClickForm f = new ClickForm();
f.setSize(400, 300);
f.addMouseListener(new MouseAdapter() {
Thread cp = null;
public void mouseClicked(MouseEvent e) {
System.out.println("getClickCount() = " + e.getClickCount() + ", e: " + e.toString());
if (cp != null && cp.isAlive()) cp.interrupt();
if (e.getClickCount() == 2) {
cp = new Thread(new ClickProcessor(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.println("Double click processed");
return null;
}
}));
cp.start();
}
if (e.getClickCount() == 3) {
cp = new Thread(new ClickProcessor(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.println("Triple click processed");
return null;
}
}));
cp.start();
}
}
});
f.setVisible(true);
}
}
You need to delay the execution of double click to check if its a tripple click.
Hint.
if getClickCount()==2 then put it to wait.. for say like 200ms?
It's exactly the same problem as detecting double-click without firing single click. You have to delay firing an event until you're sure there isn't a following click.
There's a tutorial for this
here
Edit: It fires click events individually though, so you would get:
Single Click THEN
Double Click THEN
Triple Click. So you would still have to do some timing trickery.
The code is:
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class Main {
public static void main(String[] argv) throws Exception {
JTextField component = new JTextField();
component.addMouseListener(new MyMouseListener());
JFrame f = new JFrame();
f.add(component);
f.setSize(300, 300);
f.setVisible(true);
component.addMouseListener(new MyMouseListener());
}
}
class MyMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() == 3) {
System.out.println("triple-click");
} else if (evt.getClickCount() == 2) {
System.out.println("double-click");
}
}
}
Here is what i have done to achieve this, this actually worked fine for me. A delay is necessary to detect the type of click. You can choose it. The following delays if a triple click can be happened within 400ms. You can decrease it to the extent till a consecutive click is not possible. If you are only worrying about the delay, then this is a highly negligible delay which must be essential to carry this out.
Here flag and t1 are global variables.
public void mouseClicked(MouseEvent e)
{
int count=e.getClickCount();
if(count==3)
{
flag=true;
System.out.println("Triple click");
}
else if(count==2)
{
try
{
t1=new Timer(1,new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
if(!flag)
System.out.println("Double click");
flag=false;
t1.stop();
}
});
t1.setInitialDelay(400);
t1.start();
}catch(Exception ex){}
}
}

Display a countdown

I need a timer implemented in my application, which will do a countdown from 10 sec - 0 sec.
and, display the countdown in a JLabel.
Here's my implementation;
...
Timer t = new Timer(1000, new List());
t.start();
}
class List implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
int sec = 0;
label.setText(""+sec);
// Do a if- condition check to see if the clock has reached to, and then stop
}
}
I was expecting the JLabel to start counting from 0 - 10 and then stop. But it doesn't. The JLabel set the value 0 and it doesn't get incremented.
UPDATE 1
t = new Timer(1000, new Listner());
t.start();
}
class Listner implements ActionListener{
private int counter = 0;
#Override
public void actionPerformed(ActionEvent e) {
lable.setText(""+ (counter++));
if (counter == 10)
t.removeActionListener(this);
}
}
You are not storing nor incrementing secs anywhere so I don't see how it should get updated, try with
Timer timer;
void start() {
timer = new Timer(1000,new List());
}
class List implements ActionListener {
private counter = 0;
#Override
public void actionPerformed(ActionEvent e) {
label.setText(""+counter++);
if (counter == 10)
timer.removeActionListener(this);
}
}
Mind that you need to store a reference to the timer somewhere to be able to remove the listener from it once countdown finished.
Well each time the timer is called it declares the int variable sec to 0. Hence the Label doesnt get updated.
You should declare the sec variable as a global variable and then in the actionPerformed method increment its value each time it is called.
public int sec = 0;
class List implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
sec++;
label.setText(""+sec);
// Do a if- condition check to see if the clock has reached to, and then stop
}
}
A complete example
public class ATimerExample {
Timer timer;
int counter = 0;
public ATimerExample() {
final JFrame frame = new JFrame("somethgi");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JLabel label = new JLabel("0");
JPanel panel = new JPanel();
panel.add(label, BorderLayout.SOUTH);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText(String.valueOf(counter));
counter++;
if (counter == 10) {
//timer.removeActionListener(this);
timer.stop();
}
}
});
timer.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ATimerExample();
}
});
}
}
Since java reads the time in milliseconds, it should be 10000 instead of 1000. try your code and see if that works. I had the same problem when I wanted 30 seconds. And instead of writing Timer t = new Timer(30000, new List()); t.start();
I wrote Timer t = new Timer(3000, new List());
t.start();
That made my program to stop every after 3 seconds. I would suggest, you use 10000 instead of 1000.
Remember to do: t.stop() in your List class. Thanks

Repeated down arrow key pressed in Jtable

On JTable, when down arrow key is pressed repeatedly, multiple KeyEvents are fired in quick succession. My requirement is that I need to act only on last KeyEvent. I am trying to use TimerTask in KeySelectionListener, but it is giving inconclusive results.
Any idea what changes can be done in KeyListener ?
Sample code -
addKeyListener(new KeyListener() {
Timer t = new Timer();
TimerTask tt;
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
tt.cancel();
tt = null;
}
#Override
public void keyPressed(KeyEvent e) {
if (tt != null)
return;
tt = new TimerTask() {
#Override
public void run() {
System.out.println("Selected-- "+getModel().getValueAt(getSelectedRow(), 2));
}
};
// t.scheduleAtFixedRate(tt, 0, 500);
t.schedule(tt, 0, 200);
}
});
Thanks
The idea with a Timer (and I strongly suggest to use the javax.swing.Timer class since you interact with Swing components) should work.
Just set the repeats to false, start the timer when you receive a keystroke if the timer is not running, or restart the timer when the timer is already running. This will cause a slight delay in the handling of the last key (delay = the delay you set on the timer), but avoid that you react on each key stroke
I used Timer only. I maintained reference of KeyEvent in listener and if another KeyEvent is received in pre-defined delay (for testing kept it 1 sec), new event is referneced. Thus when there is no new keyEvent for 1 sec, last referred event is used for further processing. its working for now. Feel free to suggest your opinions.
addKeyListener(new KeyListener() {
KeyEvent eventToProcess;
Timer t = new Timer();
TimerTask tt;
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(tt != null){
tt.cancel();
tt = null;
}
}
#Override
public void keyReleased(KeyEvent e) {
eventToProcess = e;
tt = new TimerTask() {
#Override
public void run() {
System.out.println("Selected-- "+getModel().getValueAt(getSelectedRow(), 2)+" Key Event > "+eventToProcess.getKeyChar());
}
};
t.schedule(tt, 1000);
}
});

Categories