Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Swing Timer and Date Class thread question...  RSS feed

 
te thompson
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi-

I have written an Swing application that displays the time in a status bar and is refreshed with a Swing Timer. Everything seems to be working fine, with one exception. I have been doing some testing changing the system time on Windows XP, and this is where I have experienced some wierd behavior. Everything works as expected if I increment the time using Adjust Date/Time in windows, but when I decrement the time, the application fails with no exception or any clue as to what is going on. I was thinking this might be a synchronization issue. Any thoughts are greatly appreciated. A working code snippet which exhibits this behavior is pasted below. Any ideas??? Thanks in advance.

-TT

import java.util.Date;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import javax.swing.*;

public class TimerProblem extends JPanel {
private static JLabel clockLabel = new JLabel("Clock Error");
private static Timer clockTimer;
public TimerProblem() {

}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
System.out.println(e);
}
createAndShowGUI();
}
});
clockTimer = new Timer (1000, new ActionListener() {
public void actionPerformed (ActionEvent event) {
System.out.println("Clock timer event start");
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss aaa z");
String time = new String(sdf.format(d));
clockLabel.setText(" " + time + " ");
System.out.println(time);
System.out.println("Clock timer event start");
}
});
clockTimer.start();
}
private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Remote Starter Demo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
clockTimer.stop();
System.exit(0);
}});
TimerProblem main = new TimerProblem();
main.add(clockLabel);
main.setOpaque(true);
frame.setContentPane(main);
frame.pack();
frame.setVisible(true);
}
}
 
Henry Wong
author
Sheriff
Posts: 22818
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When using timers, be careful with changing the system time.

Internally, it uses the system time to determine how long to wait, and whether it is time to fire another event.

Henry
 
te thompson
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry-

Thanks for the super quick response. As you have stated, I am trying to be careful using timers and the system time and I ran across this problem. I am writing an application that would have to function through windows automatically changing for daylight savings time for example. Is there any workaround??? Would a Thread sub class using sleep() do any good here, or I am assuming sleep() uses system time too??? Still thinking... Thanks.

-TT
 
Henry Wong
author
Sheriff
Posts: 22818
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The timers definitely use the system time. I don't believe the sleep() method does. So if your algorithm can use sleep() instead, which is less reliable (can be interupted), I suggest that you create a new thread with a loop that sleeps and fires the event.

One issue though. The swing timer runs the code with the event processing thread. Your new thread will not. From this new thread, don't call swing components directly -- use the SwingUtilites.invokeLater() method.

Henry
 
te thompson
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry-

You nailed it! Thanks again for the super quick response. I was definitely using the Timer class because it was thread safe with my GUI. Wanted to try to avoid any traditional Thread objects and the added complexity. As long as I call the GUI update with SwingUtilites.invokeLater() I should still be thread safe??? The only thing I am going to do in this thread is update that single JLabel with the current system time. I am going to code it up right now and try it out. I'll post with the results in a few. Thanks again.

-TT
 
Henry Wong
author
Sheriff
Posts: 22818
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As long as I call the GUI update with SwingUtilites.invokeLater() I should still be thread safe???


Yes.
 
te thompson
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, so after a little time away from this problem, I finally implemented the suggested work around, and made some progress, but am still getting some very starnge behavior.

Now, with new timer implmentation (code pasted below), I have successfully kept my label updating through a adjusting the time backwards in windows, but this is where things get strange. I had originally implemented only the label's setText call on the event thread. All other lines (the printlns, and re-intializing the date and time variables) were not implemented on the event thread. At this point the label updated through the time change, but the all the printlns stopped working. So, I went ahead and moved all of these to the event thread in an attempt to see if this would miraculously solve the problem (didn't think it would, but i don't understand whats happening well enough to be sure) and it did not. Exact same behavior.
Through all of this and more critical, the MyTimer thread never dies and the application can never exit, throughout everything I have tried. Tried setting it as a daemon thread to resolve this, but to no avail. I'm really stuck here and have two quesions...

1. Is my implmentation of MyTimer sound??? Like, I said before, everything works fine, except when the time is turned back (only, back and not forward) using Windows XP Adjust Data/Time, so I believe the implementation is sound. The code is pasted below.

2. One thought I had was trying to catch an event or an exception when the thread dies (or even if it dies???), but I have no idea where I would get it from. I don't know how or when MyTimer thread dies, if it dies, or what is going on here. Any ideas???

Thanks ahead of time, to anyone who has some suggestions.

-TT

package TimerProblem;

import java.util.Date;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import javax.swing.*;

public class TimerProblem extends JPanel {
private static JLabel clockLabel = new JLabel("Clock Error");
public TimerProblem() {

}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
System.out.println(e);
}
createAndShowGUI();
}
});

// Init and start MyTimer
MyTimer mt = new MyTimer();
Thread t = new Thread(mt);
t.setDaemon(true);
t.start();
}
private static class MyTimer implements Runnable {
Date d;
String time;
public void run() {
for(; {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
System.out.println("Clock timer event start");
d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss aaa z");
time = new String(sdf.format(d));
clockLabel.setText(" " + time + " ");
System.out.println(time);
System.out.println("Clock timer event start");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Remote Starter Demo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}});
TimerProblem main = new TimerProblem();
main.add(clockLabel);
main.setOpaque(true);
frame.setContentPane(main);
frame.pack();
frame.setVisible(true);
}
}
 
Henry Wong
author
Sheriff
Posts: 22818
119
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just by "eyeballing" it, it looks fine to me. I don't see anything that is a major problem.

I just have a minor concern. You blindly send an "invoke later" to the event dispatching thread every second. How do you know that the previous one is already done?

Depending on the amount of work needed to be done, you can overwhelm the system. It can be so backlogged with your requests, that it won't have time to process its own request efficiently.

Henry
 
te thompson
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ran another test this morning and am starting to understand the problem a little more. This is what I believe is happening now, but I am still a little fuzzy on some of the details.

When I set the clock back in time 1 hr, the label continues to update on the event thread and the time variables are re-initialized, the prinlns still do nothing. If i try to exit the application either using the close button or within my IDE (I think MyTimer thread never dies) the application will not exit. If I let the app run for exactly that 1 hr I set it back, everything begins to work as expected.

This leads me to believe, the sleep call uses the system time as well, but this still doesn't make much sense, since I am able to get the time and set it in the label no problem.

Henry- Thanks for the comment about the 1 sec refresh. I will most likely change that to every 30 secs and remove the seconds from the label. Good point.

So, this is my last attempt for now... unless I get any new ideas. I would still love to understand what is really happening under the hood though. Thanks in advance for any responses.

-TT
 
te thompson
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oops... one more detail I should add. The test was run with the exact same code in my previous post with the MyTimer class.

-TT
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!