Confusion with Thread.sleep ( adding delay )
Hey folks, have something that I suspect is an easy problem to resolve but I don't know enough yet about how threads work so ...
My main class I have using the Runnable interface and creating a new thread it. It calls a method in another helper class which does alot of calculations and as it goes it updates the text within a textpane. I wanted to slow down that process so the user can watch the update but not have it fly by, so I added
Thread.sleep( 3600 )
before each jTextPane1.setText().
What ends up happening is that the screen doesn't repaint itself until the final calculation so the above is only slowing the calculations down, not the output which gets dumped in one refresh at the end.
The main class is a JApplet and it has all of the components, can anyone suggest what I need to change to accomplish the desired textpane updating?
Thanks for any help! :)
-Andy
[929 byte] By [
AndyGCa] at [2007-11-27 8:28:51]

My gut feeling tells me that Thread.sleep is a bad method of doing this, but you could always make the JFrame or whatever you're using revalidate itself after each call. JFrame.revalidate(), or JTextArea.revalidate().
Something like:
public void calculate() {
doCalculations();
myJTextArea.revalidate();
Thread.sleep(1000); // obviously using try and catch here
}
Message was edited by:
Djaunl
Hmm, just tried that but it doesn't seem to have any impact, the textpane stll does not refresh until the helper class's method finishes... I tried the revalidate method on the JTextPane itself, not on any of its parents ( a JPanel within a JTabbedPane ).
I wish I knew of a better way than Tusing Thread.sleep, am certainly open to suggestions!
Thanks!
Andy
Can you post sample code?
I can, but the whole program is very long now so I am wondering which parts do you think would be mot helpful to see, just the method that is exhibing the problem?-Andy
Yes, that would probably be enough.
Ok, the method that is illustrating the problem is posted below... A couple of notes:
1. I put some comments where the call to update the JTextPane is
2. ht is the instance of the calling JApplet and I created a public method revalidatePlay() which calls the revalidate() method for the component.
3. Everything works fine except that the TextPane does not refresh at all until this method completes execution.
Hope this helps, I'm really stumped.
Thanks,
Andy
public void doExplore2(){
ComboCard[] comboCards = combo.comboCards;
String perm = new String();
String output = new String();
int count = 1;
ComboCard cc1 = comboCards[0]; // Combo Card #1
ComboCard cc2 = comboCards[1]; // Combo Card #2
Card c1;// Card #1 from CardSet
Card c2;// Card #2 from CarSet
if ( cc1.cardtype == cc2.cardtype ){
// Looking for 2 of the same type
for ( int i = 0; i < lenCardSet; i++ ){
c1 = cards[i];
if ( ( ( cc1.cardtype == '*' ) || ( cc1.cardtype == c1.cardtype ) ) &&
( ( cc1.family == '*' ) || ( cc1.family == 'x' ) || ( cc1.family == c1.family ) ) &&
( ( cc1.cardnum == '*' ) || ( cc1.cardnum == c1.cardnum ) ) )
{
//ht.updatePlay( "i=(" + Integer.toString(i) + ") c1: " + c1.symbol );
for ( int j = i; j < lenCardSet; j++ ){
if ( j == i ) continue;
c2 = cards[j];
if ( ( ( cc2.cardtype == '*' ) || ( cc2.cardtype == c2.cardtype ) ) &&
( ( cc2.family == '*' ) || ( cc2.family == c2.family ) ||
( ( cc1.family == 'x' ) && ( cc2.family == 'x' ) && ( c1.family == c2.family ) ) ) &&
( ( cc2.cardnum == '*' ) || ( cc2.cardnum == c2.cardnum ) ) )
{
String c1ID = ht.lookupCardID( i );
String c2ID = ht.lookupCardID( j );
try{
thread.sleep( 1000 );
}catch( InterruptedException e ){ System.out.println( "Error:" + e.getMessage() ); }
// This line calls the method in the main JApplet which calls
// revalidate for the JTextPane component
ht.revalidatePlay();
// The sleep method is not throwing any exceptions, I can see
// the slowed down execution with the System.out.printlns
System.out.println( "c1:" + c1.symbol + " [" + c1ID + "] c2:" + c2.symbol + " [" + c2ID + "]" );
output = String.format( "%-6s %14s %14s", Integer.toString( count++ ) + "." ,
"[" + Integer.toString(i) + "][" + Integer.toString(j) + "]",
c1.symbol + " , " + c2.symbol );
ht.updatePlay( output );
//ht.updatePlay( Integer.toString( count++ ) + ". [" + Integer.toString(i) + "][" + Integer.toString(j) + "] " + c1.symbol + " , " + c2.symbol );
}
}
}
}
}
}
This seems to work for me, though it is not an applet.
import javax.swing.*;
public class JFrameTest extends JFrame
{
private JTextField xField;
public static void main(String [] args)
{
new JFrameTest();
}
public JFrameTest()
{
setSize(125,75);
setTitle("Test");
xField=new JTextField("");
xField.setBounds(10,10,100,20);
this.getContentPane().setLayout(null);;
this.getContentPane().add(xField);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
doCalc();
}
//Do some "calculations"
public void doCalc()
{
try
{
Thread sleeper = new Thread();
int counter=1;
xField.setText(""+counter);
while(counter < 60 )
{
sleeper.sleep(1000);
xField.setText(""+(++counter));
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
So, if I am reading you correctly, I think that you are trying to slow down the display of information but without slowing down its calculation. Is this right? And are you using Swing? If so, you might want to look into the SwingWorker class. It may be what you are looking for:
http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html
Also, consider posting an example that is short like yours is, but is compilable. While you won't want to duplicate your calculations, you can use a simple calculation that takes a bit of time (for instance running through a couple of nested for loops) as a replacement. The key is that the example should be compilable on its own without need for other packages or non-posted classes.
Good luck!
That's awesome....I did not know about this class (haven't even updated to 1.6 yet).
Otherwise, the solution to your problem would be to do this:
Thread t = new Thread () {
public void run(){
try {
//do your calculations here
Thread.sleep( 1000 );
} catch(Exception e) {
e.printStackTrace();
}
}
};
t.start();
Thats great, I appreciate both the Thread example and the suggestion to look into SwingWorker which I plan to do next.
I applied the Thread example and it works, I had to fiddle around with changing a number of locals to be final to make the compiler stop complaining but it works and thats certainly farther than I was! ;)
Thanks to all of you for taking the time to try to help me work through that
mess, much appreciated!
:)
-Andy