Frage

How can I append text to webengine? I tried this:

public TabMessage(String title) {
    super(title);
    view = new WebView();
    engine = view.getEngine();
    engine.loadContent("<body></body>");
    view.setPrefHeight(240);
}

private void append(String msg){
    Document doc = engine.getDocument();
    Element el = doc.getElementById("body");
    String s = el.getTextContent();
    el.setTextContent(s+msg);
}

But document is null

War es hilfreich?

Lösung 2

You can also use JavaScript to do the append.

final WebEngine appendEngine = view.getEngine();
btn.setOnAction(new EventHandler<ActionEvent>() {
 @Override public void handle(ActionEvent event) {
   appendEngine.executeScript(
     "document.getElementById('content').appendChild(document.createTextNode('World!'));"
   );
 }
});

I sometimes find it simpler to use jQuery to manipulate the DOM rather than the Java Document or native JavaScript DOM interfaces.

final WebEngine appendEngine = view.getEngine();
btn.setOnAction(new EventHandler<ActionEvent>() {
 @Override public void handle(ActionEvent event) {
   executejQuery(appendEngine, "$('#content').append('World!');");
 }
});

...

private static Object executejQuery(final WebEngine engine, String script) {
  return engine.executeScript(
    "(function(window, document, version, callback) { "
    + "var j, d;"
    + "var loaded = false;"
    + "if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, loaded)) {"
    + " var script = document.createElement(\"script\");"
    + " script.type = \"text/javascript\";"
    + " script.src = \"http://code.jquery.com/jquery-1.7.2.min.js\";"
    + " script.onload = script.onreadystatechange = function() {"
    + " if (!loaded && (!(d = this.readyState) || d == \"loaded\" || d == \"complete\")) {"
    + " callback((j = window.jQuery).noConflict(1), loaded = true);"
    + " j(script).remove();"
    + " }"
    + " };"
    + " document.documentElement.childNodes[0].appendChild(script) "
    + "} "
    + "})(window, document, \"1.7.2\", function($, jquery_loaded) {" + script + "});"
  );
}

Whether you use the Java Document API, as Uluk has, or JavaScript or JQuery APIs, all of the other points in Uluk's excellent answer still apply.

Andere Tipps

First, Document returns null if webengine fails to load the content or you call engine.getDocument() before the content is fully finished its loading.

Second, doc.getElementById("body") searches for the DOM element with id "body". However the loaded content by you has no such id or any id at all.

To understand these better here is a complete runnable example, click on the button:

package demo;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Demo extends Application {

    private WebView view;
    private WebEngine engine;

    @Override
    public void start(Stage primaryStage) {

        view = new WebView();
        engine = view.getEngine();
        engine.loadContent("<body><div id='content'>Hello </div></body>");
        view.setPrefHeight(240);

        Button btn = new Button("Append the \"World!\"");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                append(" \"World!\"");
            }
        });

        StackPane root = new StackPane();
        root.getChildren().addAll(view, btn);
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void append(String msg) {
        Document doc = engine.getDocument();
        Element el = doc.getElementById("content");
        String s = el.getTextContent();
        el.setTextContent(s + msg);
    }

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

Note that I have put a div with id=content in th body so doc.getElementById("content") returns that div.

Though answer is very old and already accepted, I am putting my finding here.

The trick was to call engine.loadContent in init method of controller and then try to append content on some action like mentioned in example btn.setOnAction(). This way when you have action fired, the page was already loaded. If I put code for loading in setOnAction() itself, I get document as null.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top