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]
# 1

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

Djaunla at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 2

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

AndyGCa at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 3
Can you post sample code?
hoozdapimpa at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 4
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
AndyGCa at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 5
Yes, that would probably be enough.
hoozdapimpa at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 6

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 );

}

}

}

}

}

}

AndyGCa at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 7

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();

}

}

}

hoozdapimpa at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 8

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!

petes1234a at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 9

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();

hoozdapimpa at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...
# 10

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

AndyGCa at 2007-7-12 20:18:58 > top of Java-index,Java Essentials,New To Java...