JavaFX自动滚动自动更新文本 [英] JavaFX auto-scroll auto-update text

查看:191
本文介绍了JavaFX自动滚动自动更新文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于JavaFX的新手问题,我无法回答,尽管知道它必须非常简单,并且在我看过的任何地方都没有找到任何资源(教程,许多Oracle在线文档,文章,众所周知的JavaFX博主等。)

Newbie question about JavaFX that I haven't been able to answer, despite knowing it must be pretty simple to do and not finding any resources on it anywhere I've looked (tutorials, many of the Oracle online docs, articles, the well-known JavaFX bloggers, etc.)

我正在开发一个运行应用程序的命令行(脚本),我已成功从脚本中获取输出(通过ProcessBuilder)我可以以持续的方式显示,就像在命令行上发生的那样。也就是说,我可以整天做 System.out.println(line); ,在控制台中显示输出,它只返回由返回的输入流的输出'myProcess'正在运行,创建如下:

I'm developing a command line (script) running application and I have successfully gotten output (via ProcessBuilder) from the script that I can display in an ongoing manner, as things happen on the command line. That is, I can do System.out.println(line); all day long, showing the output in the console, which simply returns output from an input stream returned by the 'myProcess' that's running, created like this:

BufferedReader bri = new BufferedReader(new InputStreamReader(myProcess.getInputStream()))

所以我能够看到从脚本返回的所有输出。

So I am able to see all the output coming back from the script.

我想设置一个JavaFX TextArea或ScrollPane,或者不确定是什么,以显示这个输出文本(有很多,如几千行)作为一个持续的'进展正如脚本中发生的那样。我有一个场景,我有按钮并从这个场景获取输入以启动脚本运行,但现在我想显示点击运行此脚本按钮的结果,可以这么说。

I'd like to set-up a JavaFX TextArea or ScrollPane or, not sure what, to display this output text (there's a lot of it, like several thousand lines) as an ongoing 'progress' of what's taking place in the script, as it happens. I have a Scene, I have buttons and get input from this scene to start the script running, but now I'd like to show the result of clicking the button "RUN THIS SCRIPT", so to speak.

我假设我需要创建一个这里描述的TextArea 或者可能是 TextBuilder 对于开始制作它很有用。不确定。

I assume I need to create a TextArea as described here or perhaps a TextBuilder would be useful to begin making it. Not sure.

我需要一些帮助,如何设置绑定或自动滚动/自动更新部分。

I need a bit of help in how to setup the binding or auto-scroll/auto-update part of this.

有人可以给我一个开始的地方,用JavaFX做这个吗?我宁愿不使用Swing。

Can someone provide me a place to start, to do this with JavaFX? I'd rather not use Swing.

(我使用的是JavaFX 2.2,JDK 1.7u7,所有最新的东西,是的,这是一个FXML应用程序 - 所以这样做是首选。)

(I'm using JavaFX 2.2, JDK 1.7u7, all the latest stuff, and yes, this is an FXML app--so doing it that way would be preferred.)

更新:谢尔盖·格里内夫的回答对绑定部分非常有帮助。但是,当我要求如何设置一些帮助时,这里有一些更详细的信息 - 基本上,我需要将控制权返回到主场景以允许用户取消脚本,或者以其他方式监视这是怎么回事。所以我想生成运行该脚本的进程(也就是说,有某种'自由运行进程'),但仍然从中获取输出。 (我在最初的问题中对此并不是很清楚。)

UPDATE: Sergey Grinev's answer was very helpful in the binding part. But here is some more detail on what I mean when I ask for "a bit of help in how to setup" -- basically, I need to return control to the main Scene to allow the user to Cancel the script, or to otherwise monitor what's going on. So I'd like to "spawn" the process that runs that script (that is, have some kind of 'free running process'), but still get the output from it. (I wasn't very clear on that in my initial question.)

我在这里使用的技术(见下文)是在进程中进行waitFor,但当然这意味着脚本执行时对话框/场景是挂起的。我想获得控制权,但是如何将'p'(进程)传递给其他控制器部分(或者,只需启动其他进程传入参数以启动脚本并让它启动脚本)然后通过绑定Sergey Grinev提到自动更新 - 没有挂场景/窗口?另外:如果用户请求,我可以停止这个其他过程吗?

The technique I'm using here (see below) is to do a waitFor on the process, but of course this means the dialog/Scene is 'hung' while the script executes. I'd like to gain control back, but how do I pass the 'p' (Process) to some other controller piece (or alternatively, simply kick off that other process passing in the parameters to start the script and have it start the script) that will then do the auto-update, via the binding Sergey Grinev mentions--without 'hanging' the Scene/window? Also: Can I then 'stop' this other process if the user requests it?

这是我当前的代码('等待'而脚本 - 需要20-40分钟运行! - 完成;这是我想要的东西,我想让控件返回给用户):

Here is my current code ('waits' while script--which takes 20-40 min to run!--completes; this is not what I want, I'd like control returned to the user):

public class MyController implements Initializable {  
  @FXML
  private void handleRunScript(ActionEvent event) throws IOException {

    ProcessBuilder pb = new ProcessBuilder("myscript.sh", "arg1", "arg2", ...);

    Process p = pb.start();
    try {
      BufferedReader bri = new BufferedReader
        (new InputStreamReader(p.getInputStream()));
      String line;

      while ((line = bri.readLine()) != null) {
        System.out.println(line);
        textAreaRight.setText(line);
      }
      bri.close();
      p.waitFor();
    }
    catch (Exception err) {
      err.printStackTrace();
    }    
  }

  @FXML
  private void handleCancel(ActionEvent event) {
    doSomethingDifferent();
  }
}


推荐答案


  1. 要记录字符串,您可以使用TextArea

  2. 要使其不同步,您需要为输出阅读器创建一个单独的线程。







public class DoTextAreaLog extends Application {

    TextArea log = new TextArea();
    Process p;

    @Override
    public void start(Stage stage) {
        try {
            ProcessBuilder pb = new ProcessBuilder("ping", "stackoverflow.com", "-n", "100");

            p = pb.start();

            // this thread will read from process without blocking an application
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //try-with-resources from jdk7, change it back if you use older jdk
                        try (BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
                            String line;

                            while ((line = bri.readLine()) != null) {
                                log(line);
                            }
                        }
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();

            stage.setScene(new Scene(new Group(log), 400, 300));
            stage.show();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    @Override
    public void stop() throws Exception {
        super.stop();
        // this called on fx app close, you may call it in user action handler
        if (p!=null ) {
            p.destroy();
        }
    }

    private void log(final String st) {
        // we can access fx objects only from fx thread
        // so we need to wrap log access into Platform#runLater
        Platform.runLater(new Runnable() {

            @Override
            public void run() {
                log.setText(st + "\n" + log.getText());
            }
        });
    }

    public static void main(String[] args) {
        launch();
    }
}

这篇关于JavaFX自动滚动自动更新文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆