4

Я знаю, что тема уже была замечена во многих Вопросах, и мне ответили, но все же я не могу получить ее.Обновление JProgressBar во время обработки

Я просто хочу, чтобы обновил progressBar, извлекая некоторые вещи из большого файла xml. Я думал, что этого достаточно, чтобы иметь длительный цикл в другом потоке, но? .. Все, что мне удалось получить, это progressBar, который либо не был показан вообще, либо обновлен в конце, незадолго до его закрытия.

Instanced где-то рядом с запуском приложения, у меня есть:

public class SomeClass { 
    private SomeClass() { 
     myXMLParser reader = new myXMLParser(); 
     CoolStuff fromXml = reader.readTheXml(); 
    } 
} 

, показывая и обновляя JDialog с JProgressBar:

public class LoadingDialog extends JDialog { 
    private JProgressBar progressBar; 
    /* ... */ 
    public void progress() { 
     progressBar.setValue(progressBar.getValue() + 1); 
    } 
} 

Так что у меня этот myXMLParser:

public class myXMLParser { 
    private LoadingDialog loadingDialog = new LoadingDialog(); 

    public CoolStuff readTheXml() { 
     CoolStuff fromXml = new CoolStuff(); 
     while(manyIterations) { 
      loadingDialog.progress(); 
      fromXml.add(some() + xml() + reading()); 
     } 
     return fromXml; 
    } 
} 

Я видел много вещей w с SwingWorker и с использованием PropertyChange событий обновляют progressBar, но всегда приводятся примеры все-в-одном с обработкой и панель прогресса в пределах одного класса и с классами внутри классов, а так как я начинаю на Java, я wasn ' я могу перевести это в свою ситуацию.

Любая помощь? .. Любые (не слишком очевидные) советы?

Edit: Так благодаря btantlinger она работала так:

public class SomeClass { 
    private SomeClass() { 
     myXMLParser reader = new myXMLParser(); 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       CoolStuff fromXml = reader.readTheXml(); 
      } 
     }).start(); 
    } 
} 

public class LoadingDialog extends JDialog { 
    private JProgressBar progressBar; 
    /* ... */ 
    public void progress() { 
     progressBar.setValue(progressBar.getValue() + 1); 
    } 
} 

public class myXMLParser { 
    private LoadingDialog loadingDialog = new LoadingDialog(); 

    public CoolStuff readTheXml() { 
     CoolStuff fromXml = new CoolStuff(); 
     while(manyIterations) { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        loadingDialog.progress(); 
       } 
      }); 
      fromXml.add(some() + xml() + reading()); 
     } 
     return fromXml; 
    } 
} 

ответ

10

Вы должны обновить панель JProgress на свинг диспетчерской Event Thread. Вы не можете изменять компоненты Swing в любом другом потоке.

Ваш единственный альтернативный вариант заключается в том, чтобы установить панель JProgress «неопределенно», прежде чем вы начнете свою нить, когда индикатор выполнения будет идти туда и обратно.

Например

progBar.setIndeterminate(true); 

См SwingWorker документацию: http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html

Если вы не хотите использовать SwingWorker, другой вариант является SwingUtilities.invokeLater метод

//inside your long running thread when you want to update a Swing component 
SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 

     //This will be called on the EDT 
     progressBar.setValue(progressBar.getValue() + 1); 


    } 
}); 
0

В дополнение к код, предоставленный @btantlinger, я обнаружил после тестирования, что для обновления требуется дополнительная строка кода e индикатор выполнения в потоке пользовательского интерфейса во время обработки. Смотри ниже.

SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     progressBar.setValue((int)percentage); 
     //below code to update progress bar while running on thread 
     progressBar.update(progressBar.getGraphics());} 
    });