JavaFX TextArea appendText适用于初始化,但不适用于其他地方

时间:2016-09-14 22:56:55

标签: javafx fxml

简单的问题,但它让我发疯。

在我的程序中,我有TextArea,定义为:

<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();
    }
}

关于如何让文字出现的任何想法都会很棒,我之前已经在不同的节目中做过这件事,只是出于某种原因,这次它是不好的

编辑:进一步修改后,它实际上会打印出结果,但只有在Process结束后它才会退出循环。

2 个答案:

答案 0 :(得分:3)

UI中显示的文本在布局脉冲上发生变化。布局脉冲在JavaFX应用程序线程上完成。事件处理程序(如download方法)在同一个线程上运行,有效地阻止它在完成之前进行任何布局或处理以及其他事件。这就是为什么你不应该用冗长的任务来阻止这个线程,而是在不同的线程上执行它们。

由于应该从应用程序线程对UI进行更新,因此请使用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();
}

答案 1 :(得分: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();
}