Re: Do I need Threads for this?
nospam@invalid.invalid wrote:
I've got a method that copies files from one place to another. Each time the
file copies over it takes roughly 10 seconds per file (depending on how
large the file is).
In the meantime, I need my JPanel label to update with the current number of
files copied over so far.
I know from looking at the FAQs for this newsgroup that the GUI isn't
updating because it probably needs a new thread, but as a complete newbie to
threads, I'm wondering if I really need to learn about Threads to get my
relatively simple job done. My code simply runs in a for loop -
int count=0;
for (int i=0; i < 12; i++) {
mycopyOverFileMethod();
count++;
label.setText("Files Copied:" + count);
// Why is there no simple way in java just to put here something like :
// label.redraw();
// that avoids the need for threads??
}
Is there something simple I could do?
TIA
OK, brace yourself :)
Yes, you will need threaded code to do this, but it should be reasonably
simple. You will need a basic understanding of threading in Java but it
is quite straightforward to do things like this.
Repaint will not work because it will simply queue the component for
repainting when the AWT thread (EDT) is available, and it wont be
available until your method returns.
Once you have gotten to grips with the basics of threading, create a
Runnable that does the file copy, and in between each file copy, change
your label text... however... there is something else you must understand...
You should not do any manipulation of visual components on any thread
but the AWT thread, visual components are not thread safe and may behave
strangely if you do not follow this rule. Fortunately, there is a class
called SwingUtilities that will allow you to pass tasks from your worker
thread to the AWT thread. SwingUtilities.invokeLater(Runnable) will
allow you to provide a task which will be run at some point (when AWT
thread gets around to it) and SwingUtilities.invokeAndWait(Runnable)
will pass the task on a block until it has been ran. You probably want
the latter in this case.
So, your code will look something similar to this...
private final JLabel statusLabel;
public void copyFiles()
{
Thread copyThread = new Thread(new Runnable()
{
public void run()
{
while(...)//there are more files to copy
{
//copy file
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
//Increment label value
}
});
}
}
}).start();
}
....but clean it up a bit :)