2015-08-27 12 views
5

Ho un'applicazione JavaFX che fa un uso pesante di una WebView. Sto cercando di inserire un oggetto nel DOM che possa essere utilizzato dal codice JavaScript e ho bisogno che questi oggetti siano disponibili quando vengono caricate nuove pagine.Perché il metodo JavaScript non viene eseguito quando inserito nel DOM da JavaFX?

Tuttavia, quando eseguo il programma, FirebugLite mostra l'oggetto nel DOM, ma le funzioni non vengono eseguite.

Secondo some Oracle documentation, questo sembra essere il modo appropriato per fornire i ritardi da JavaScript a Java. Ho anche visto alcuni StackOverflow posts spiegando la stessa cosa.

Cosa mi manca? Sto utilizzando Java 8, aggiornamento 51, 64 bit su Windows 7.

Java:

public class DemoApplication extends Application { 

    Debug debug; 

    @Override 
    public void start(final Stage stage) throws Exception { 
     debug = new Debug(); 

     WebView browser = new WebView(); 
     WebEngine webEngine = browser.getEngine(); 
     webEngine.getLoadWorker().stateProperty().addListener(
       new ChangeListener<Worker.State>() { 
        @Override 
        public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) { 
         if (newValue == Worker.State.SUCCEEDED) { 
          JSObject windowObject = (JSObject) webEngine.executeScript("window"); 
          windowObject.setMember("Debug", debug); 
         } 
        } 
       } 
     ); 
     webEngine.load("http://localhost:8080/page1.html"); 

     stage.setScene(new Scene(browser)); 
     stage.show(); 
    } 

} 

public class Debug { 
    public void print(final Object text) { 
     System.err.println(text); 
    } 
} 

HTML/JavaScript:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title></title> 
    <script type="text/javascript" src="https://getfirebug.com/firebug-lite.js"></script> 
    <script> 
    Debug.print("Hello"); 
    </script> 
</head> 
<body> 
    Page 1 
    <a href="page2.html">Page 2</a> 
</body> 
</html> 

Firebug Screenshot:

enter image description here

risposta

3

Credo che quello che sta accadendo è che WebEngine carica la pagina, il ChangeListener è in provocato in vari punti (PROGRAMMATO, IN CORSO, RIUSCITO, ecc.). Una volta che si verifica l'evento Worker.State.SUCCEEDED, la pagina ha già completato il caricamento di tutto il contenuto e ha terminato eseguendo tale contenuto anche. Quindi in pratica le mie chiamate a Debug.print() nel codice JavaScript stavano accadendo presto e chiamando un oggetto che era indefinito o null.

Questa è la mia ipotesi migliore in ogni caso, perché se aggiungo una funzione JavaScript che viene eseguita dalla porzione Java dopo l'aggiunta di negli oggetti, tutto funziona come previsto.

Ecco come ho modificato il JavaScript lato:

<script> 
    // callback that uses java objects 
    window.ready = function() { 
    Debug.print("Hello"); 
    } 
</script> 

e questo è come ho modificato il lato Java:

webEngine.getLoadWorker().stateProperty().addListener(
    new ChangeListener<Worker.State>() { 
     @Override 
     public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) { 
      if (newValue == Worker.State.SUCCEEDED) { 
       JSObject windowObject = (JSObject) webEngine.executeScript("window"); 
       windowObject.setMember("Debug", debug); // insert object 
       windowObject.call("ready"); // execute callback 
      } 
     } 
    } 
); 

I cambiamenti chiave sono la funzione di pronto() in JavaScript e invocando quella funzione dopo iniettando gli oggetti sul lato Java. Questo assicura che questi oggetti siano disponibili prima di essere chiamati.

Ho provato questo su poche pagine diverse e passando da una pagina all'altra, quando la funzione ready() si chiamava Debug.print() eseguita correttamente, anche quando si utilizza WebEngine.reload() o WebHistory.go ().

Problemi correlati