0

I have a problem, right now in reloading a html file on my webview component.

So, basically, when i run the application, my html file works very well on my program (HTML file located at my local storage).

But when i want to reload the html file ( by doing the reaload action on my webview), it seems like there is a problem with my tunnel (which i created for interaction with another javafx component) and my html document has a different behaviour as It should have...

package Visual.SintaxDirectedEditor;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Screen;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
import org.fxmisc.richtext.CodeArea;
import org.fxmisc.richtext.LineNumberFactory;

import java.io.File;

public class Main {
 private Scene scene;
 private Stage stage;
 private final String title = "liss | SDE";
 private final double width = 600;
 private final double height = 400;
 private final double cX = 0.00, cY = 0.00;


public Main() throws Exception {

    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("sde.fxml"));
    AnchorPane page = (AnchorPane) fxmlLoader.load();
    scene = new Scene(page);

    stage = new Stage();
    stage.setScene(scene);
    stage.setTitle(this.title);

    //Maximize the menubar width with parent node
    //MenuBar mb = (MenuBar) scene.lookup("#menuBar");
    //mb.prefWidthProperty().bind(stage.widthProperty());

    //Set minimum width and height of the window
    stage.setMinWidth(width);
    stage.setMinHeight(height);

    //Maximize window
    Screen screen = Screen.getPrimary();
    Rectangle2D bounds = screen.getVisualBounds();

    stage.setX(bounds.getMinX());
    stage.setY(bounds.getMinY());
    stage.setWidth(bounds.getWidth());
    stage.setHeight(bounds.getHeight());

    //Set coordinates of the window
    //stage.setY(cY);
    //stage.setX(cX);


    WebView wv = (WebView) fxmlLoader.getNamespace().get("tree");
    StackPane sp = (StackPane) fxmlLoader.getNamespace().get("code_editor");

    //Add Html file to WebEngine and set the context menu of the HTML file false
    File f = new File("ressources/html/index.html");
    WebEngine we = wv.getEngine();
    we.setJavaScriptEnabled(true);
    we.load(f.toURI().toURL().toString());
    wv.setContextMenuEnabled(false);

    //Add the RichText plugin to JavaFx application
    CodeArea codeArea = new CodeArea();
    codeArea.setParagraphGraphicFactory(LineNumberFactory.get(codeArea));
    codeArea.setEditable(false);
    codeArea.setStyle("-fx-font-size:15;");
    sp.getChildren().add(codeArea);

    //Creating a bridge for WebEngine to Java code application
    JSObject jsobj = (JSObject) we.executeScript("window");
    LissProgram l = new LissProgram(codeArea);
    jsobj.setMember("liss", l);


    //When "close menuitem" is clicked, then it exits the program
    MenuItem closeMenuItem = (MenuItem) fxmlLoader.getNamespace().get("close");
    closeMenuItem.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent e) {
            Platform.exit();
        }
    });

    //When the "new menuitem" is clicked, then it must create
    MenuItem newMenuItem = (MenuItem) fxmlLoader.getNamespace().get("new");
    newMenuItem.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent e) {
            wv.getEngine().reload();
        }
    });


    stage.show();
 }

}

What's wrong with my code ?

2
  • When you say 'tunnel', what do you mean? The bridge between the JavaFX application and your HTML page (respectivly the JavaScript therein)? Commented Feb 17, 2016 at 6:56
  • @hotzst yes, that tunnel/bridge :p ! Commented Feb 17, 2016 at 11:41

2 Answers 2

1

You register a bridge with these lines of code:

//Creating a bridge for WebEngine to Java code application
JSObject jsobj = (JSObject) we.executeScript("window");
final LissProgram lissProg = new LissProgram(codeArea);
jsobj.setMember("liss", lissProg);

What actually happens is that a JavaScript object liss is created on the global context (window). However when you reload the page, the global context is reloaded as well. Therefore you have to re-register liss after the reload:

//When the "new menuitem" is clicked, then it must create
MenuItem newMenuItem = (MenuItem) fxmlLoader.getNamespace().get("new");
newMenuItem.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent e) {
        final WebEngine webEngine = wv.getEngine();
        webEngine .reload();
        webEngine.getLoadWorker().stateProperty().addListener(
        new ChangeListener<State>() {
            public void changed(ObservableValue ov, State oldState, State newState) {
                if (newState == State.SUCCEEDED) {
                    JSObject jsobj = (JSObject) we.executeScript("window");
                    jsobj.setMember("liss", lissProg);
                }
            }
        });

    }
});
Sign up to request clarification or add additional context in comments.

6 Comments

So instead of doing it on my addListener i do on my "newMenuItem" then ?
Tried what you said, and If i let this piece of code by removing the one which I answered. It won't work properly ! So what I did, It was to let both of the code, and it works as well. But I'm really confused with that sincerely ....
I changed the answer so that it should work now. The issue that it was not working was that the bridge can only be initialized successfully after the page is loaded, otherwise it will fail silently. By adding a listener on the state this can be achieved.
Thanks bro for the help ! :)
Which library did you use for State and ObservableValue ?
|
0

Ok, so I finally did manage in solving the problem by adding a function to my webengine !

By doing this:

//Creating a bridge for WebEngine to Java code application
    we.documentProperty().addListener((observable, oldValue, newValue) -> {
        //Comment about this piece of code: When a user want to create a new liss file, we must add this piece of code into the function addListener function.
        JSObject jsobj = (JSObject) we.executeScript("window");
        LissProgram l = new LissProgram(codeArea);
        jsobj.setMember("liss", l);
    });

I added a "addListener" function and change my JSObject there. Now, my page reload and the tunnel/bridge works perfectly. Hope that It will help for future developers.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.