Java, чтение входного потока внутри jButton actionperformed

Я пытаюсь прочитать входной поток процесса, который я создаю внутри функции actionPerformed JButton для своего интерфейса. Для этой цели я реализовал исполняемый класс. Проблема в том, что я получаю поток вывода в квантах, то есть, скажем, я получаю 50 строк, затем большую паузу и еще 50 строк и тому подобное. Большая проблема заключается в том, что порядок строк не соответствует. Вот как выглядит мой код...

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt)
{
  try{
    String sCommand = "cmd /c \"myenvsetup.bat && myprogram.exe\"";
    Runtime rt = Runtime.getRuntime();
    pr = rt.exec(sCommand);
    java.awt.EventQueue.invokeLater(new Runnable()
    {
      public void run()
      {
        try{
          BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
          String line = null;
          while((line = input.readLine()) != null){
            jTextArea1.append(line + "\n");
            jTextArea1.scrollRectToVisible(new Rectangle(0, jTextArea1.getHeight(), 0, 0));
            jTextArea1.update(jTextArea1.getGraphics());
          }
          pr.waitFor();
        } catch (Exception e) {
        }
      }
    });
  } catch (Exception e){
  }
}

person thisiserdinc    schedule 15.03.2016    source источник
comment
Для примера пример, < href="http://stackoverflow.com/questions/15801069/printing-a-java-inputstream-from-a-process/15801490#15801490">пример. Вероятная причина - вызов update, который вам никогда не нужно было делать   -  person MadProgrammer    schedule 15.03.2016


Ответы (2)


Короче говоря, вы не должны блокировать ввод-вывод в потоке событий. Используйте другую нить,

person user207421    schedule 15.03.2016
comment
Я также пробовал это. Я реализовал исполняемый класс и создал новый поток сразу после выполнения программы. Все тот же выход. - person thisiserdinc; 15.03.2016

Вы должны использовать свинг работника. Я написал пример с использованием исполнителя для выполнения ввода-вывода.

ExecutorService executor = newSingleThreadExecutor()

Цель этого примера — показать, что вы выполняете свою работу в потоке исполнителя, а затем отправляете свои изменения в EDT.

try {
    String sCommand = "cmd /c \"myenvsetup.bat && myprogram.exe\"";
    Runtime rt = Runtime.getRuntime();
    pr = rt.exec(sCommand);
    executor.submit(new Runnable() {
      public void run(){
        try{
            BufferedReader input = new BufferedReader(
              new InputStreamReader(pr.getInputStream())
            );
            String line = null;
            while((line = input.readLine()) != null){
                final String l = line;
                EventQueue.invokeLater(new Runnable(){
                  @Override
                  public void run(){
                     jTextArea1.append(l + "\n");
                     jTextArea1.scrollRectToVisible(
                       new Rectangle(0, jTextArea1.getHeight(), 0, 0)
                     );
                     jTextArea1.repaint();
                 }
                });
              }
              pr.waitFor();
        } catch (Exception e) {}
      }
   });
} catch (Exception e){
}

Класс SwingWorker позаботится о выполнении работы вне EDT и позволит вам опубликовать работу. Это больше подходит для данной ситуации.

И вы не должны использовать .update(Graphics g).

person matt    schedule 15.03.2016
comment
Просто используйте SwingWorker, это проще и имеет publish/process функциональные возможности для безопасной синхронизации обновлений пользовательского интерфейса. - person MadProgrammer; 15.03.2016