2016-09-14 2 views
0

간단하지만 충분히 문제가 있습니다.JavaFX TextArea appendText는 초기화에서 작동하지만 다른 곳에서는 작동하지 않습니다.

<TextArea fx:id="output" editable="false" prefHeight="300.0" prefWidth="200.0" text="Output" GridPane.columnSpan="2" GridPane.rowIndex="4" /> 
@FXML private TextArea output; 

... 

public void initialize(URL url, ResourceBundle rb) { 
    output.setText("Test"); //Test appears correctly in output 
    ... 
} 

@FXML 
public void download() { 
    String outputTemplate = templateField.getText(); 
    String url = urlField.getText(); 
    System.out.println("Downloading from " + url); 
    try { 
     Process down = Runtime.getRuntime().exec("youtube-dl -o \"" + outputTemplate + "\" " + url); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(down.getInputStream())); 
     String line; 
     while ((line = reader.readLine()) != null) { 
      System.out.println(line); //Prints as expected 
      output.appendText(line + "\n"); //Has no effect 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

좋은 것입니다 표시 할 텍스트를 얻는 방법에 대한 아이디어, 나는 다른 프로그램에 전에 이런 짓을 한 : 나의 프로그램에서

I는 TextArea을 정의 그냥 어떤 이유로, 이번에는 캔트가되고있다.

EDIT : 추가로 조정하면 실제로는 결과가 인쇄되지만 Process이 끝나고 루프를 종료 한 후에 만 ​​인쇄됩니다.

답변

3

UI에 표시된 텍스트가 레이아웃 펄스에 따라 바뀝니다. 레이아웃 펄스는 JavaFX 응용 프로그램 스레드에서 수행됩니다. download 메서드와 같은 이벤트 처리기는 동일한 스레드에서 실행되어 효과적으로 완료 될 때까지 레이아웃이나 처리 및 기타 이벤트를 수행하지 못하게합니다. 따라서 장기간 실행되는 작업에서는이 스레드를 차단하지 말고 다른 스레드에서 실행해야합니다. 사용자 인터페이스 업데이트는 응용 프로그램 스레드에서 수행해야하기 때문에

, 텍스트를 추가 할 Platform.runLater를 사용

@FXML 
public void download() { 
    String outputTemplate = templateField.getText(); 
    String url = urlField.getText(); 
    Runnable r =() -> { 
     System.out.println("Downloading from " + url); 
     try { 
      Process down = Runtime.getRuntime().exec("youtube-dl -o \"" + outputTemplate + "\" " + url); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(down.getInputStream())); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       System.out.println(line); //Prints as expected 
       final String printText = line + "\n"; 

       // append the line on the application thread 
       Platform.runLater(() -> output.appendText(printText)); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    }; 
    // run task on different thread 
    Thread t = new Thread(r); 
    t.start(); 
} 
0

문제는 주 스레드에서 문제가 발생한다는 것입니다. 주기가 완료 될 때까지 스테이지를 업데이트 할 수 없습니다. 새 스레드에서 사용해보십시오.

@FXML 
public void download() { 
    Task<Void> task = new Task<Void>() { 
     @Override 
     protected Void call() { 
      String outputTemplate = templateField.getText(); 
      String url = urlField.getText(); 
      System.out.println("Downloading from " + url); 
      try { 
       Process down = Runtime.getRuntime().exec("youtube-dl -o \"" + outputTemplate + "\" " + url); 
       BufferedReader reader = new BufferedReader(new InputStreamReader(down.getInputStream())); 
       String line; 
       while ((line = reader.readLine()) != null) { 
        System.out.println(line); // Prints as expected 
        output.appendText(line + "\n"); // Has no effect 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return null; 
     } 
    }; 
    new Thread(task).start(); 
} 
+0

당신은 백그라운드 스레드에서'output'을 수정할 수 없습니다. –

+0

왜 안 되니? 그것은 작동합니다. 아니면 스레드로부터 안전하지 않다는 것을 의미합니까? – gearquicker

+0

스레드로부터 안전하지 않습니다. [Javadocs] (http://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html)에서 "라이브 객체 수정은 JavaFX 응용 프로그램 스레드에서 수행해야합니다". 따라서 특정 플랫폼에서 작동하는 동안 일반적으로 작동한다는 보장은 없습니다. –

관련 문제