Прогрессбар в потоке не обновляет свой интерфейс, пока работа не будет выполнена в основном потоке - PullRequest
2 голосов
/ 24 октября 2011

Я разрезаю большой файл на блоки и хочу показать скорость выполнения.когда я нажимаю кнопку startCut, вот код для выполнения:

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++;
}

Я меняю значение индикатора выполнения за пределами метода run в месте B, проблема в том, что - grogressbar показывает только два состояния:0% и 100%.но, если я уберу код в месте B и изменим значение индикатора выполнения внутри метода run в месте A, проблема исчезнет.я знаю, что с SwingWorker это можно легко исправить, но я хочу знать, почему это происходит, хотя я изменяю значение в методе run, когда я распечатываю его в методе run, оно действительно меняется.Как я могу исправить эту проблему при изменении значения вне метода run?

Ответы [ 3 ]

6 голосов
/ 24 октября 2011

Суть проблемы в том, что вы обновляете компонент: pbCompleteness в потоке , отличном от потока отправки событий .Вы можете исправить это, используя SwingUtilities.invokeLater из вашего run() метода;например,

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

  // Do some work and update value.
}

Это приведет к обновлению (и перерисовке) JProgressBar в потоке диспетчеризации событий, так как ваш рабочий поток продолжает работать.Обратите внимание, что для ссылки на value внутри "внутреннего" анонимного экземпляра Runnable я изменил его на AtomicInteger.Это также желательно, так как делает потокобезопасным.

3 голосов
/ 24 октября 2011

У вас есть две проблемы:

  • Вы выполняете длительную работу в потоке диспетчера Swing, что означает, что вы останавливаете его от обработки событий.(Попробуйте переместить окна вокруг и т. Д. - это не удастся.)
  • Вы обновляете пользовательский интерфейс из неправильного потока в точке А. Похоже, что вам это сходит с рук в данный момент, но это все ещеошибка.

Вы должны использовать SwingWorker или SwingUtilities для решения обеих этих проблем.По сути, вы не должны получать доступ к пользовательскому интерфейсу из потока, не являющегося пользовательским интерфейсом, и не должны выполнять длительную работу над потоком пользовательского интерфейса.См. учебник по параллелизму Swing для получения дополнительной информации.

0 голосов
/ 27 июля 2013

Я нашел очень простой способ решить эту проблему: D.Вы можете использовать этот код и очень просто передать эту ошибку:).

int progress=0;
Random random = new Random();
while (progress < 100) {
 //Sleep for up to one second.
 try {
       Thread.sleep(random.nextInt(100));
} catch (InterruptedException ignore) {}
progress+=1;
progressBar.setValue(progress);
Rectangle progressRect = progressBar.getBounds();//important line 
progressRect.x = 0;
progressRect.y = 0;         
progressBar.paintImmediately(progressRect);//important line 
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...