i am cutting a big file into blocks, and want to display the rate of the progress. when i click startCut Button, here is the code to execute:
FileInputStream in = new FileInputStream(sourceFile);
int blockSize = (int)(getSelectedBlockSize() * 1024);
int totalBlock = Integer.parseInt(txtNumberOfBlock.getText());
byte[] buffer = new byte[blockSize];
int readBytes = in.read(buffer);
int fileIndex = 1;
class PBThread extends Thread
{
@Override
public void run()
{
while(true)
{
pbCompleteness.setValue(value);
//value++; //place A
System.out.println(value);
if (value >= 100)
break;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
value = 0;
PBThread pbThread = new PBThread();
pbThread.start();
while(readBytes != -1)
{
File file = new File(targetFilePath + fileIndex);
FileOutputStream out = new FileOutputStream(file);
out.write(buffer, 0, readBytes);
out.close();
value = (int)(fileIndex / (double)totalBlock * 100);// place B
readBytes = in.read(buffer);
fileIndex++;
}
i change the value of the progressbar outside the run method at place B,the problem is that --the grogressbar only show two state: 0% and 100%.
but, if i take away the code in place B, and change the value of the progressbar inside the run method at place A, the problem will disappear.
i know maybe with SwingWorker
it can be fixed easily, but i do want to know why this happen,although i change the value out the run method,when i print it out in the run method,it did changed.
how can i fix that problem while changing value outside the run method?
i found a very simple way to this prob :D . you can use this code and very simlpe handel this error :).
The crux of the problem is that you're updating the component:
pbCompleteness
on a thread other than the Event Dispatch Thread. You can remedy this usingSwingUtilities.invokeLater
from within yourrun()
method; e.g.This will cause the
JProgressBar
to be updated (and repainted) on the Event Dispatch thread as your worker thread continues to run. Note that in order to refer tovalue
within the "inner" anonymousRunnable
instance I have changed it to be anAtomicInteger
. This is also desirable as it makes it thread-safe.You've got two problems here:
You should use
SwingWorker
orSwingUtilities
to address both of these issues. Basically, you mustn't access the UI from a non-UI thread, and you mustn't do long-running work on a UI thread. See the Swing concurrency tutorial for more information.