Timer + gregorianCalendar.getTime() not refreshing date properly - java

where I made mistake? I tried to show current time in window every sec.
But it show
ActionListener AL = new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
Date currentTime=gregorianCalendarCurrrentTime.getTime();
JLabelCurrentTime.setText(String.valueOf(currentTime));
}
};
Timer timer = new Timer(1000, AL);
timer.start();

Assuming, that gregorianCalendarCurrrentTime is of type java.util.GregorianCalendar, the method getTime() returns a Date object which is representing the time of the calendar-objekt which was 'current' at creation time or after last use of set-methods of the calendar-objekt. The method does not determine the current time. To set the current time as labeltext, you simply could use new Date().
LabelCurrentTime.setText(String.valueOf(new Date()));

Related

JAVA SWING - Creating Animation using Swing Timer

I am trying to setup a program that enables the user to display a transition when clicking the next and previous button. When pressing next, the swing timer should trigger and start the animation. When transitioning, there should be a flag that states it is in the transition period. The Swing timer should fire once every tenth of a second and essentially last 1 second.
public class guiCreation {
static Timer timer;
static boolean flag = false;
private static void guiInterface() {
next.addActionListener(new ActionListener(){
timer = new Timer(1000, this);
public void actionPerformed(ActionEvent e){
nextGest();
}
});
//should go to the next tab
previous.addActionListener(new ActionListener(){
//if the list gets to the beginning, disable button
public void actionPerformed(ActionEvent e){
prevGest();
}
});
}
public static void nextGest() {
timer.start();
previous.setEnabled(true);
next.setEnabled(true);
//if the list gets to the end, disable button
if (cardLayout.isNextCardAvailable()) {
status.setText(" Next button has been clicked");
//System.out.println("This is the" + size);
cardLayout.next(cardPanel);
next.setEnabled(cardLayout.isNextCardAvailable());
}
}
public static void prevGest() {
if (cardLayout.isPreviousCardAvailable()) {
timer.start();
next.setEnabled(true);
previous.setEnabled(true);
status.setText(" Previous button has been clicked");
cardLayout.previous(cardPanel);
previous.setEnabled(cardLayout.isPreviousCardAvailable());
}
}
}
This: "The Swing timer should fire once every tenth of a second ..." -- does not agree with this: timer = new Timer(1000, this); Your Timer is firing once every second, not every 10th of a second.
Instead, you should:
Create a new Timer(100, ...), one that fires every 10th of a second
Store in an instance field the start time in msecs when the Timer begins (likely do this in your button's ActionListener)
Within the Timer's ActionListener get the current mSecs and use this to check the elapsed time
Stop the Timer via ((Timer) e.getSource()).stop(); once 1 full second has elapsed
No need for a flag, since all you need to do is to check if the Timer isn't null and if it .isRunning(). e.g., if (timer != null && timer.isRunning()) { -- then the animation is proceeding.
Unrelated suggestion:
Get out of the static world and into the instance world. You're programming in Java, a language that is built to use OOPs from the ground up, and you don't want to fight against the OOPs paradigm.

timer in java button

I don't know how to put this code insid emy programs . Likee..if I click on the button or by mouse in JPanel (that's inside the original panel), the program will run
static class Action implements ActionListener(){
public void actionPerformed (ActionEvent e){
long serialVersionUID = 1L;
Timer timer;
long startTime = -1;
long duration = 1200000 ;
JLabel label = new JLabel;
timer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
}
long now = System.currentTimeMillis();
long clockTime = now - startTime;
if (clockTime >= duration) {
clockTime = duration;
timer.stop();
}
SimpleDateFormat df = new SimpleDateFormat("mm:ss:SSS");
label.setText(df.format(duration - clockTime));
}
});
This is a typical problem of new programmers finding code then copying it and pasting it wherever they think is might work. As you've already realized....it's not that simple otherwise you obviously wouldn't be here seeking assistance.
There are a number of things going wrong with your provided code and this is exactly why I'll provide you with code to show you how this can work using a Local Timer within a JButton Action Event and point out some of the specific problems so that you can realize them for later on should you encounter this sort of thing again.
You don't need to declare your timer variable and then initialize it later on down the road. You can declare and initialize the timer variable right on the same line, for example:
final Timer timer = new Timer(10, new ActionListener() {
..................
..................
..................
});
Your Long data type startTime variable will never work within a Local Timer or any Inner (local) Class for that matter where value changes will need to be made. For your startTime variable to be used within the Local Timer Class it needs to carry full scope there and to do that the variable needs to be declared as final. Uhhh, there is a problem with this though, you can not change the value within a final variable which is a requirement for this countdown timer to function properly. If we don't declare the startTime variable as final then we'll just end up with a "local variables referenced from an inner class must be final or effectively final" compile error. The solution to this then is to declare and initialize the startTime variable within the Local Timer class itself like this:
final Timer timer = new Timer(10, new ActionListener() {
long startTime = -1;
#Override
public void actionPerformed(ActionEvent event) {
..................
..................
}
});
That solves that little problem. Now you have yet another problem, you can't just up and stop your Timer from within itself using the Timer.stop() method as you've done (ie: timer.stop(); ) within the Timer's actionPerformed event for the simple reason the variable timer has no proper scope there and can't see that it's been initialized. Yes, it'll probably compile and it'll most likely run right up until the timer.stop() method is called and then you'll end up getting a Runtime Exception ("variable timer might not have been initialized"). Not good, and don't think about catching the exception and letting bygones be bygones because your ultimately not stopping the Timer (crappy practice). You just need to get a little fancier with your stop and this will do the trick:
((Timer)event.getSource()).stop();
//event is the ActionEvent variable (usually evt in some IDE's).
Now, your duration variable, there is nothing wrong with this if you like to supply long number values for even 1 minute of timing. Works great if that's your thing but for me personally, I like simply entering 60 instead of 60000. It really doesn't matter if the value will be hard coded into place but if it will actually be a supplied value (regardless from where) then it's just better to supply seconds (IMHO) which would of course entail the use of an additional variable, for example:
int seconds = 10;
final long duration = seconds * 1000;
Now you only need to supply the number of seconds you want your Countdown Timer to be set at.
Another problem you have is that you've declared a variable named label to represent a JLabel but nowhere do you either reference that variable to an actual JLabel somewhere or add it to a frame or panel component. I thinking that you've already installed a JLabel within your GUI (if you have a GUI) in which case you will need to supply that JLabel variable name when you declare the label variable, like this:
JLabel label = (JLabel)jLabel1;
This way the label variable represents the JLabel named jLabel1 within your GUI.
And finally (and this is a biggy) your Timer simply wont run if you don't tell it to do so. Where do you do this, well, right under your Local Timer Class of course :) like this:
final Timer timer = new Timer(10, new ActionListener() {
long startTime = -1;
#Override
public void actionPerformed(ActionEvent event) {
..................
..................
}
});
timer.start();
Anyways, here's is the full code as promised:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int seconds = 10; // supply timer duration in seconds
final long duration = seconds * 1000; // calculate to milliseconds
JLabel label = (JLabel)jLabel1; //whichever JLabel is in GUI
final Timer timer = new Timer(10, new ActionListener() {
long startTime = -1;
#Override
public void actionPerformed(ActionEvent event) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
}
long now = System.currentTimeMillis();
long clockTime = now - startTime;
if (clockTime >= duration) {
clockTime = duration;
((Timer)event.getSource()).stop(); // stop the Timer
label.setText("Time Is UP"); // remove if you want or maybe just ""
return;
}
SimpleDateFormat df = new SimpleDateFormat("mm:ss:SSS");
label.setText(df.format(duration - clockTime));
}
});
timer.start();
}

How does JSpinner stateChanged works?

Why does the code enters twice in the change event of the JSpinner?
private javax.swing.JSpinner spinner = new javax.swing.JSpinner()
spinner.setModel(new javax.swing.SpinnerDateModel());
spinner.addChangeListener(new javax.swing.event.ChangeListener() {
#Override
public void stateChanged(javax.swing.event.ChangeEvent evt) {
System.out.println("Just a test");
}
});
The code above shows the message twice when u click only one time.
2 events are generated: one for the value being deselected and another for the new value being selected in the component. As #camickr notes in his comment this behavior occurs in SpinnerDateModel but not in the default SpinnerNumberModel
As a workaround you could use
spinner.addChangeListener(new ChangeListener() {
Object lastValue;
#Override
public void stateChanged(ChangeEvent evt) {
if (lastValue != null && !spinner.getValue().equals(lastValue)) {
// expensive code calls here!
}
lastValue = spinner.getValue();
}
});
This wont prevent the listener being called twice but will prevent any expensive code being invoked unnecessarily
Just bumped into the same problem and found a different workaround, as the one in https://stackoverflow.com/a/19166589/5326620 caused it to miss the event when first editing the date directly on the text field.
In my case, I'm using a SpinnerDateModel for Calendar.DAY_OF_MONTH (same as Calendar.DATE).
If the SpinnerDateModel is initialized with a value precisely at midnight, the event is no longer fired twice.
Calendar now = Calendar.getInstance();
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
Date value = now.getTime();
JSpinner dateSpn = new JSpinner(new SpinnerDateModel(value, null, null, Calendar.DAY_OF_MONTH));
This is probably because the commitEdit of the JFormattedTextField tests the old and new value by equality, and Date equality is on the millisecond.

Using SwingWorker and Timer to display time on a label?

I want to have a clock showing current time and refreshes every second. The code I am using is:
int timeDelay = 1000;
ActionListener time;
time = new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
timeLabel.setText(DateTimeUtil.getTime());
/*timeLabel is a JLabel to display time,
getTime() is samll static methos to return formatted String of current time */
}
};
SwingWorker timeWorker = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
new Timer(timeDelay, time).start();
return null;
}
};
timeWorker.execute();
What I want to refresh the timeLabel text in another thread other than EDT.
Am I doing it correct? Any other better way?
Also for information, i've added timeLabel to a extendedJPanel which contains few similar kinds of utilities, and is called in another MainJFrame.
You can do this without a SwingWorker, because this is what the Swing Timer is made for.
int timeDelay = 1000;
ActionListener time;
time = new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
timeLabel.setText(DateTimeUtil.getTime());
/* timeLabel is a JLabel to display time,
getTime() is samll static methos to return
formatted String of current time */
}
};
new Timer(timeDelay, time).start();

Creating digital clock using a thread

I am trying to create a digital clock using a Thread as this seems to me the logical way one would do it.
I am not sure if I am going about it the right way but what I had in mind is to create the initial current System time using the JFrame constructor and display it as text using a label. In the constructor I then create the thread object with which to update the time.
Struggling a bit and was hoping for some advice as to how to do it right.
setDefaultCloseOperation((JFrame.EXIT_ON_CLOSE));
setBounds(50, 50, 200, 200);
JPanel pane = new JPanel();
label = new JLabel();
//Font localTime = new Font("Lumina", Font.BOLD , 24);
pane.add(label);
add(pane);
sdf = new SimpleDateFormat("HH:mm:ss");
date = new Date();
s = sdf.format(date);
label.setText(s);
setVisible(true);
runner = new Thread(this);
while(runner == null)
{
runner = new Thread(this);
runner.start();
}
This is then my run() method to update the clock every second.
public void run()
{
while(true)
{
try
{
Thread.sleep(1000);
sdf = new SimpleDateFormat("HH:mm:ss");
date = new Date();
s = sdf.format(date);
label.setText(s);
}
catch(Exception e){}
}
Main method.
public static void main(String[] args)
{
new DigitalClock().setVisible(true);
}
The label state should be updated in the Event Dispatch Thread.
You need to add the following modification:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setText(s);
}
});
instead of simply updating the label from the separate thread.
It's worth to have a look at the simple description of The Swing GUI Freezing Problem and it's simple solution.
What do you want to improve? It looks ok, while(runner == null) not necessary, you're initialising runner just above.
Check this class http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html
scheduleAtFixedRate(TimerTask task, long delay, long period) is probably what you need.

Categories