Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
521 views
in Technique[技术] by (71.8m points)

java - progressbar in a thread does not update its UI until the work was done in the main thread

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 using SwingUtilities.invokeLater from within your run() method; e.g.

AtomicInteger value = new AtomicInteger(0);
while (true) {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      pbCompleteness.setValue(value.get());
    }
  });

  // Do some work and update value.
}

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 to value within the "inner" anonymous Runnable instance I have changed it to be an AtomicInteger. This is also desirable as it makes it thread-safe.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...