0

我正在创建一个运行程序的 GUI,该程序运行测试并将其输出作为文本写入控制台。我创建了一个表,允许用户选择他们想要运行的测试,当用户单击“运行”时,它会遍历表并运行选定的测试,并且应该将输出写入 textArea。当我运行程序时,textArea 在运行所有测试之前不会更新,但我需要它在测试输出文本时更新。

根据我的阅读,我需要创建多个线程,因为运行程序和写入 textArea 都是进程。我对 Threading 的工作原理并没有真正的了解,但我尝试过使用 StringBuffer,以便我创建的第二个 Thread 可以存储和使用测试的输出。

public void runTest(ArrayList<String> arr) throws InterruptedException{
        StringBuffer sb = new StringBuffer();

        Thread t = new Thread(() -> {
            try {
                ProcessBuilder builder = new ProcessBuilder(arr);
                builder.redirectErrorStream(true);
                Process p = builder.start();
                BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line;
                while((line = r.readLine()) != null){
                    sb.append(line).append("\n");
                }  
                System.out.println(line);
            } catch (IOException ex) {
                Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
            }
        });

        Thread t2 = new Thread(()->{
            String line = sb.toString();
            System.out.println(line);
            txtOutputArea.appendText(line + "\n");
        });

        t.start();
        t2.start();

        t.join();
        t2.join();

    }

我正在将文本打印到控制台,它可以工作,但由于某种原因,textArea 没有输出。

4

2 回答 2

1

在一个线程中执行它,就像这样txtOutputArea.appendText(line + "\n");在线程一中的 while 循环中移动并将其包装在 a 中Platform.runlater,这样它就不会像这样在主线程上抛出一个 not 异常。

private ExecutorService executorService = Executors.newSingleThreadExecutor();

public void runTest(ArrayList<String> arr) throws InterruptedException{
    Thread t = new Thread(() -> {
        try {
            ProcessBuilder builder = new ProcessBuilder(arr);
            builder.redirectErrorStream(true);
            Process p = builder.start();
            BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while((line = r.readLine()) != null){
                //sb.append(line).append("\n");//Remove this if thats all you were using it for
                Platform.runLater(()->txtOutputArea.appendText(line + "\n"));
            }
            System.out.println(line);//Move this inside the loop if you want it to print th output to the console
        } catch (IOException ex) {
            Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
        }
    });
    executorService.submit(t);
}

要像@Slaw 所说的那样添加此问题,如果您使用 anewSingleThreadExecutor这将导致您提交给此服务的所有内容都像队列一样被处理,因此如果您调用runTest然后运行您的第二个测试并将其提交给executorService(和第一个一样)。它将不得不等待,因为executorService.

于 2019-03-28T18:06:00.353 回答
-1

附带说明:请注意,如果 TextArea 中的文本太长,JavaFX TextArea 的性能将非常糟糕。因此,如果您的输出可能变成几千行,这将不起作用(由于 TextAre 没有虚拟化)。

于 2019-03-29T15:38:42.950 回答