javafx 以一种方法将多个字符串添加到 TextArea -> Everything is written once at the end

javafx adding multiple strings into TextArea in one method -> Everything is written once at the end

我有一个 javafx 程序,我想用它来分析网站。一开始我只想将站点的源代码打印到 TextArea 中,但在此之前,我写 "loading website sourcecode..."

我的目标是先写 "loading website sourcecode...",然后在网站解析完成几秒钟后,添加源代码。

在我按下按钮的那一刻,没有任何反应,3-5 秒后立即显示 "loading website sourcecode..." 消息和源代码。

所以我其实是想一个接一个地显示字符串。我已经用谷歌搜索了 2 个小时,并尝试了线程、invokelater、platform.runLater() 等等,但没有任何效果,代码很简单。

ModelView.java - 控制器 Class

package root;

import javafx.application.Platform;
...

public class ModelView {

    @FXML public TextField UrlInput;

    // This gets called when the button is pressed
    public void checkUrl() throws InterruptedException
    {
        String url = UrlInput.getText();

        LogWriter lw = new LogWriter();

        lw.printMsg("loading website sourcecode...");
        lw.printMsg(HTMLParser.directUrlToCode(url));
    }
}

LogWriter.java

package root;

import javafx.beans.value.ObservableValue;
...

public class LogWriter extends Thread{

    @FXML TextArea Log;

    public LogWriter()
    {
        Log = (TextArea) Main.scene.lookup("#Log");
    }

    void printMsg(String s)
    {
        Log.setText(this.Log.getText()+"\n"+s);
    }
}

编辑:

关于 HTMLParser 方法没有太多可说的,但我补充说它扩展了 Thread。

我尝试将 ModelView.java 更改为:

ModelView.java - 版本 2

package root;

import javafx.application.Platform;
...

public class ModelView<V> {

    @FXML public TextField UrlInput;

    // This gets called when the button is pressed
    public void checkUrl() throws InterruptedException
    {
        String url = UrlInput.getText();

        LogWriter lw0 = new LogWriter();
        lw0.start();
        lw0.printMsg("loading website sourcecode...");

        HTMLParser hp = new HTMLParser();
        hp.start();

        LogWriter lw1 = new LogWriter();
        lw1.start();
        lw1.printMsg(hp.directUrlToCode(url));

    }
}

还是一样的效果

编辑2:

这是我试过的另一个版本,在这种情况下,"loading website sourcecode..."甚至没有显示,我继续尝试...

ModelView.java checkUrl() - 版本 3

public void checkUrl() throws InterruptedException
{
    String url = UrlInput.getText();

    Task<Void> task = new Task<Void>(){
        @Override protected Void call() throws Exception {
            if(isCancelled()) {
                updateMessage("Cancelled");
                LogWriter lw = new LogWriter();
                lw.printMsg("loading website sourcecode...");
            }
            return null;
        }
    };

    Thread t = new Thread(task);
    t.start();

    HTMLParser hp = new HTMLParser();
    LogWriter lw1 = new LogWriter();
    lw1.printMsg(hp.directUrlToCode(url));

}

首先,从 JavaFX 应用程序线程外部操作可观察变量不是一个好主意。您将无法将其他变量绑定到它(您将得到 IllegalStateExceptions)

其次,我会像这样实现 LogWriter

// ...
public class LogWriter {

    private final TextArea txtLog;

    public LogWriter(TextArea txtLog) {
        this.txtLog = txtLog;
    }

    void printMsg(final String s) {
        if (!Platform.isFxApplicationThread()) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    printMsg(s);
                }
            });
        } else {
            txtLog.setText(txtLog.getText() + "\n" + s);
        }
    }
}

并这样使用它:

//...

@FXML
private TextArea txtLog;

// ...

public void checkUrl() {
    final String url = UrlInput.getText();
    final LogWriter lw = new LogWriter(txtLog);

    Task<String> task = new Task<String>() {

        @Override
        protected String call() {
            lw.printMsg("loading website sourcecode...");
            return HTMLParser.directUrlToCode(url);
        }

        @Override
        protected void succeeded() {
            super.succeeded();
            lw.printMsg(getValue());
        }

        @Override
        protected void failed() {
            super.failed();
            if (getException() != null) {
                getException().printStackTrace();
            }
            lw.printMsg("failed!");
        }
    };

    new Thread(task).start();
}

请注意 HTMLParser 不需要扩展 Thread