2017-10-14 5 views
3

Je fais une application basée sur le Web avec le soutien de Java pour certaines demandes particulières (par exemple, imprimer sans choisir l'imprimante à chaque fois) et il y a quelque chose qui m'aide à conduire fou.JavaFX JSObject ne fonctionne plus après quelques minutes?

J'utilise JavaFX pour instancier l'objet du navigateur et tout fonctionne très bien, mais bien sûr, je dois faire callbacks de JavaScript à Java, voici le code:

... 
... 
we.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() 
    { 
     @Override 
     public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) 
     { 
      if (newValue == Worker.State.SUCCEEDED) 
      { 
       bridge = new Bridge(); 
       JSObject jsobj = (JSObject) we.executeScript("window"); 
       jsobj.setMember("app", new Bridge()); 
      } 

      if (newValue == Worker.State.CANCELLED) 
      { 
       System.out.println(newValue); 
       System.out.println("An error accourred"); 
      } 
     } 
    }); 
    ... 
    ... 

Cela fonctionne, mais après quelques pont minutesthe stoo fonctionnant totalement, javascript ne peut plus faire de callbacks et si j'essaye de faire un alert() sur l'objet "app" il me renvoie undefined. J'utilise JDK9

+1

Il n'est pas trop tiré par les cheveux que le 'JSObject' ne contient que des références faibles aux membres qui lui sont passés. Pourriez-vous essayer de conserver une référence à l'instance 'Bridge'? (Il semble que vous le vouliez, mais vous en créez un tout nouveau pour le 'JSObject' ...) – Itai

+0

@sillyfly en fait, vous avez raison. Inexplicablement j'ai passé une nouvelle instance de Bridge et je ne sais pas pourquoi, javafx semble un peu intolérant aux affectations locales comme ça. Merci beaucoup. –

Répondre

1

Pour rendre la solution plus évidente: l'approche proposée par @sillyfly fonctionne. Au lieu de créer une instance Bridge (ou dans mon cas Console instance) pour chaque changement d'état, créez une instance unique et réaffectez-la à chaque fois. Quelque chose dans les lignes suivantes.

public class AppController { 
    public WebView webview; 

    @FXML 
    public void initialize() { 
     final Console console = new Console(); 
     final WebEngine engine = webview.getEngine(); 
     engine.setJavaScriptEnabled(true); 
     engine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() { 
      @Override 
      public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) { 
       final JSObject window = (JSObject) engine.executeScript("window"); 
       window.setMember("console", console); 
      } 
     }); 
    } 

    public class Console { 
     public void log(String text) { 
      System.out.println("[WebView console] " + text); 
     } 
    } 
}