B
bojanraic
I've written a simple app that displays current time and lets the user
input time to start the countdown. It works well, except for one
thing: when 'Stop' button is pressed, it should call the pause()
method, and when 'Start' button is pressed again, it should pick up
upon where it left when paused.
When I press 'Stop', the display of countdown time is indeed paused,
but when 'Start' is pressed once again, the display acts as if the
thread was not paused at all.
I am not sure how to fix this, so if someone could help me, I woul dbe
really grateful.
Here is my code:
CDThread.java - the countdown thread - I'm not sure where to put the
synchronized (this) block... maybe that is the problem. Here's the
code:
import java.awt.*;
import java.util.Date;
public class CDThread extends Thread
{
private Thread cdThread = null;
private Date cntdwnDate;
private String cntdwnString;
private boolean shouldPause;
private int secs, mins, hrs, seconds, minutes, hours;
private long endTime, pausedTime;
public CDThread()
{
super("CountDown");
if (!(TPanel.sec.getText().equals("")&&TPanel.min.getText().equals("")&&TPanel.hour.getText().equals("")))
{
secs = Integer.parseInt(TPanel.sec.getText());
mins = Integer.parseInt(TPanel.min.getText());
hrs = Integer.parseInt(TPanel.hour.getText());
}
else
{
secs = 0;
mins = 0;
hrs = 0;
}
long currentMiliseconds = new Date().getTime();
endTime = currentMiliseconds + secs*1000 + mins*60*1000 +
hrs*60*60*1000;
cntdwnDate = new Date(endTime);
start();
}
public void pause()
{
shouldPause = true;
pausedTime = System.currentTimeMillis();
}
public synchronized void pickUp()
{
shouldPause = false;
endTime = endTime - pausedTime + System.currentTimeMillis();
notifyAll();
}
// run() method
public void run()
{
while(true)
{
try
{
Date currentDate = new Date();
if (cntdwnDate.after(currentDate))
{
long dateDifference = cntdwnDate.getTime() -
currentDate.getTime();
dateDifference = dateDifference/1000;
// Get seconds
int seconds = (int) dateDifference%60;
// Get minutes
dateDifference = dateDifference/60;
int minutes = (int) dateDifference%60;
// Get hours
dateDifference = dateDifference/60;
int hours = (int) dateDifference%24;
// Countdown string
cntdwnString = hours + " hours, " + minutes + " minutes, " +
seconds + " seconds remaining...";
synchronized (this)
{
while (shouldPause)
{
try
{
wait();
}
catch (Exception e) {}
}
}
}
else
cntdwnString = "Done!";
TPanel.cntdwnLabel.setText(cntdwnString);
// Sleep for a second
Thread.sleep(1000);
if (cntdwnString.equals("Done!"))
stop();
}
catch (InterruptedException e)
{
stop();
}
}
}
}
TPanel.java - panel to layout the GUI components
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
class TPanel extends JPanel implements ActionListener
{
private JButton start, stop, clear;
protected static JLabel timeLabel, cntdwnLabel, minLabel, secLabel,
hourLabel;
protected static CDThread cntdwnThread = null;
private static String cntdwnLabelString, timeString;
private SimpleDateFormat timeFormat;
protected static int hrs, mins, secs;
private JPanel panel1, panel2, panel3;
private javax.swing.Timer t;
private DecimalFormat two;
protected static JTextField sec, min, hour;
public TPanel()
{
/*set up GUI components*/
setLayout(new BorderLayout());
panel1 = new JPanel(new BorderLayout());
panel2 = new JPanel(new FlowLayout());
panel3 = new JPanel(new FlowLayout());
start = new JButton("Start");
stop = new JButton("Stop");
clear = new JButton("Clear");
start.addActionListener(this);
stop.addActionListener(this);
clear.addActionListener(this);
sec = new JTextField(4);
min = new JTextField(4);
hour = new JTextField(4);
timeLabel = new JLabel(timeString);
timeLabel.setHorizontalAlignment(JLabel.CENTER);
cntdwnLabelString = " ";
cntdwnLabel = new JLabel(cntdwnLabelString);
cntdwnLabel.setHorizontalAlignment(JLabel.CENTER);
hourLabel = new JLabel("Hrs ");
secLabel = new JLabel("Secs ");
minLabel = new JLabel("Mins ");
panel3.add(hourLabel);
panel3.add(hour);
panel3.add(minLabel);
panel3.add(min);
panel3.add(secLabel);
panel3.add(sec);
panel2.add(start);
panel2.add(stop);
panel2.add(clear);
panel1.add(timeLabel, BorderLayout.NORTH);
panel1.add(cntdwnLabel, BorderLayout.CENTER);
add(panel3, BorderLayout.NORTH);
add(panel2, BorderLayout.CENTER);
add(panel1, BorderLayout.SOUTH);
/*set up the timer to display current time*/
two = new DecimalFormat("00");
t = new javax.swing.Timer(1000,
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Calendar now = Calendar.getInstance();
int h = now.get(Calendar.HOUR_OF_DAY);
int m = now.get(Calendar.MINUTE);
int s = now.get(Calendar.SECOND);
timeString = "Time: " + two.format(h) + ":" + two.format(m) + ":"
+ two.format(s);
timeLabel.setText(timeString);
}
});
t.start(); // Start the timer
}
public void actionPerformed(ActionEvent ae)
{
Object source = ae.getSource();
if (source == start)
{
if (cntdwnThread == null)// if there is no thread
cntdwnThread = new CDThread();// make a new thread
else // if one is running
cntdwnThread.pickUp(); // call CDThread's pickUp() resume method
}
else if (source == stop)
{
if (cntdwnThread != null)
cntdwnThread.pause();// call CDThread's pause() method
}
else if (source == clear)
{
hrs = 0;
mins = 0;
secs = 0;
if (cntdwnThread != null)
{
cntdwnThread.stop(); //stop the thread
cntdwnThread = null;
}
/*reset the text fields*/
hour.setText("");
min.setText("");
sec.setText("");
cntdwnLabelString = " ";
cntdwnLabel.setText(cntdwnLabelString);
}
}
}
TFrame.java - driver class
import java.awt.*;
import javax.swing.*;
class TFrame extends JFrame
{
private TPanel timerPanel;
public TFrame()// the constructor
{
super( "TimerTest"); // the title of the frame (window)
Toolkit tk = Toolkit.getDefaultToolkit(); // get toolkit to position
the frame
Dimension dim = tk.getScreenSize(); // get screen size
int height = 220;
int width = 260;
setBounds(((dim.width-width)/2), ((dim.height-height)/2), width,
height); // center the frame on the screen
setResizable(false); // do not allow resizing
Container container = getContentPane(); // get container
timerPanel = new TPanel(); // instantiate new object
container.add(timerPanel);
}
public static void main(String args[]) // method main
{
TFrame timer = new TFrame();
timer.show();
timer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} // end main
}
I really apologize for the length of this message, but I really can't
figure this one out. If someone can compile and run the code and tell
me what needs to be fixed, that'd be great.
Thanks in advance!
input time to start the countdown. It works well, except for one
thing: when 'Stop' button is pressed, it should call the pause()
method, and when 'Start' button is pressed again, it should pick up
upon where it left when paused.
When I press 'Stop', the display of countdown time is indeed paused,
but when 'Start' is pressed once again, the display acts as if the
thread was not paused at all.
I am not sure how to fix this, so if someone could help me, I woul dbe
really grateful.
Here is my code:
CDThread.java - the countdown thread - I'm not sure where to put the
synchronized (this) block... maybe that is the problem. Here's the
code:
import java.awt.*;
import java.util.Date;
public class CDThread extends Thread
{
private Thread cdThread = null;
private Date cntdwnDate;
private String cntdwnString;
private boolean shouldPause;
private int secs, mins, hrs, seconds, minutes, hours;
private long endTime, pausedTime;
public CDThread()
{
super("CountDown");
if (!(TPanel.sec.getText().equals("")&&TPanel.min.getText().equals("")&&TPanel.hour.getText().equals("")))
{
secs = Integer.parseInt(TPanel.sec.getText());
mins = Integer.parseInt(TPanel.min.getText());
hrs = Integer.parseInt(TPanel.hour.getText());
}
else
{
secs = 0;
mins = 0;
hrs = 0;
}
long currentMiliseconds = new Date().getTime();
endTime = currentMiliseconds + secs*1000 + mins*60*1000 +
hrs*60*60*1000;
cntdwnDate = new Date(endTime);
start();
}
public void pause()
{
shouldPause = true;
pausedTime = System.currentTimeMillis();
}
public synchronized void pickUp()
{
shouldPause = false;
endTime = endTime - pausedTime + System.currentTimeMillis();
notifyAll();
}
// run() method
public void run()
{
while(true)
{
try
{
Date currentDate = new Date();
if (cntdwnDate.after(currentDate))
{
long dateDifference = cntdwnDate.getTime() -
currentDate.getTime();
dateDifference = dateDifference/1000;
// Get seconds
int seconds = (int) dateDifference%60;
// Get minutes
dateDifference = dateDifference/60;
int minutes = (int) dateDifference%60;
// Get hours
dateDifference = dateDifference/60;
int hours = (int) dateDifference%24;
// Countdown string
cntdwnString = hours + " hours, " + minutes + " minutes, " +
seconds + " seconds remaining...";
synchronized (this)
{
while (shouldPause)
{
try
{
wait();
}
catch (Exception e) {}
}
}
}
else
cntdwnString = "Done!";
TPanel.cntdwnLabel.setText(cntdwnString);
// Sleep for a second
Thread.sleep(1000);
if (cntdwnString.equals("Done!"))
stop();
}
catch (InterruptedException e)
{
stop();
}
}
}
}
TPanel.java - panel to layout the GUI components
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
class TPanel extends JPanel implements ActionListener
{
private JButton start, stop, clear;
protected static JLabel timeLabel, cntdwnLabel, minLabel, secLabel,
hourLabel;
protected static CDThread cntdwnThread = null;
private static String cntdwnLabelString, timeString;
private SimpleDateFormat timeFormat;
protected static int hrs, mins, secs;
private JPanel panel1, panel2, panel3;
private javax.swing.Timer t;
private DecimalFormat two;
protected static JTextField sec, min, hour;
public TPanel()
{
/*set up GUI components*/
setLayout(new BorderLayout());
panel1 = new JPanel(new BorderLayout());
panel2 = new JPanel(new FlowLayout());
panel3 = new JPanel(new FlowLayout());
start = new JButton("Start");
stop = new JButton("Stop");
clear = new JButton("Clear");
start.addActionListener(this);
stop.addActionListener(this);
clear.addActionListener(this);
sec = new JTextField(4);
min = new JTextField(4);
hour = new JTextField(4);
timeLabel = new JLabel(timeString);
timeLabel.setHorizontalAlignment(JLabel.CENTER);
cntdwnLabelString = " ";
cntdwnLabel = new JLabel(cntdwnLabelString);
cntdwnLabel.setHorizontalAlignment(JLabel.CENTER);
hourLabel = new JLabel("Hrs ");
secLabel = new JLabel("Secs ");
minLabel = new JLabel("Mins ");
panel3.add(hourLabel);
panel3.add(hour);
panel3.add(minLabel);
panel3.add(min);
panel3.add(secLabel);
panel3.add(sec);
panel2.add(start);
panel2.add(stop);
panel2.add(clear);
panel1.add(timeLabel, BorderLayout.NORTH);
panel1.add(cntdwnLabel, BorderLayout.CENTER);
add(panel3, BorderLayout.NORTH);
add(panel2, BorderLayout.CENTER);
add(panel1, BorderLayout.SOUTH);
/*set up the timer to display current time*/
two = new DecimalFormat("00");
t = new javax.swing.Timer(1000,
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Calendar now = Calendar.getInstance();
int h = now.get(Calendar.HOUR_OF_DAY);
int m = now.get(Calendar.MINUTE);
int s = now.get(Calendar.SECOND);
timeString = "Time: " + two.format(h) + ":" + two.format(m) + ":"
+ two.format(s);
timeLabel.setText(timeString);
}
});
t.start(); // Start the timer
}
public void actionPerformed(ActionEvent ae)
{
Object source = ae.getSource();
if (source == start)
{
if (cntdwnThread == null)// if there is no thread
cntdwnThread = new CDThread();// make a new thread
else // if one is running
cntdwnThread.pickUp(); // call CDThread's pickUp() resume method
}
else if (source == stop)
{
if (cntdwnThread != null)
cntdwnThread.pause();// call CDThread's pause() method
}
else if (source == clear)
{
hrs = 0;
mins = 0;
secs = 0;
if (cntdwnThread != null)
{
cntdwnThread.stop(); //stop the thread
cntdwnThread = null;
}
/*reset the text fields*/
hour.setText("");
min.setText("");
sec.setText("");
cntdwnLabelString = " ";
cntdwnLabel.setText(cntdwnLabelString);
}
}
}
TFrame.java - driver class
import java.awt.*;
import javax.swing.*;
class TFrame extends JFrame
{
private TPanel timerPanel;
public TFrame()// the constructor
{
super( "TimerTest"); // the title of the frame (window)
Toolkit tk = Toolkit.getDefaultToolkit(); // get toolkit to position
the frame
Dimension dim = tk.getScreenSize(); // get screen size
int height = 220;
int width = 260;
setBounds(((dim.width-width)/2), ((dim.height-height)/2), width,
height); // center the frame on the screen
setResizable(false); // do not allow resizing
Container container = getContentPane(); // get container
timerPanel = new TPanel(); // instantiate new object
container.add(timerPanel);
}
public static void main(String args[]) // method main
{
TFrame timer = new TFrame();
timer.show();
timer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} // end main
}
I really apologize for the length of this message, but I really can't
figure this one out. If someone can compile and run the code and tell
me what needs to be fixed, that'd be great.
Thanks in advance!