2015-03-30 1 views
1

Mon but est de pouvoir mettre du contenu html dans un objet WebView dans le document fxml en utilisant la classe contrôleur. Mon document FXML contient d'autres objets comme des boutons et des images, je veux que le WebView fasse partie de l'interface graphique. Je peux mettre du contenu dans une TextArea dans le document FXML en utilisant la classe de contrôleur. Faire cela pour WebView est un peu plus compliqué car il nécessite un WebEngine pour l'accompagner. Je sais comment lancer un WebView par lui-même sans le document FXML, mais est-ce que quelqu'un sait si mon objectif est réalisable?JavaFX éditer WebView dans le document FXML

C'est ma tentative dans la classe de contrôleur, mais je reçois une exception cible d'invocation:

public class FXMLDocumentController implements Initializable { 

    @FXML 
    private Label label; 
    WebEngine engine; 

    @FXML 
    private void handleButtonAction(ActionEvent event) { 
     System.out.println("You clicked me!"); 
     label.setText("Hello World!"); 
    } 

    //access WebView in FXML document 
    @FXML WebView mywebview; //mywebview is the fxid 
    public void displayWeb() { 
     engine = mywebview.getEngine(); 
     final String hellohtml = "chang.htm"; //HTML file to view in web view 
     URL urlHello = getClass().getResource(hellohtml); 
     engine.load(urlHello.toExternalForm()); 
    } 

    @Override 
    public void initialize(URL url, ResourceBundle rb) { 
     displayWeb(); 
    }  

} 
+0

Veuillez publier la trace de la pile à partir de l'exception et identifier la ligne où se produit l'exception. –

Répondre

1

Ceci est une sorte de concept pur (au moins si je comprends bien ce que vous demandez :-). J'aime ça. Bravo pour y penser. En relisant votre question, j'ai peut-être complètement mal compris ... si c'est le cas, je suppose que vous pouvez ne pas tenir compte de ma réponse.

contenu HTML en ligne Spécification dans FXML

Malheureusement, WebView est définitive, de sorte que vous ne pouvez pas étendre simplement WebView ajouter des méthodes de chargement de contenu à un élément qui peut être spécifié dans FXML.

La solution consiste à fournir une petite classe wrapper autour du WebView que FXML peut instancier et définir du contenu. J'ai choisi de faire en sorte que la classe wrapper hérite de StackPane, de sorte que l'encapsuleur soit un nœud et puisse être instancié en FXML partout où vous voudrez utiliser un nœud. Vous pouvez utiliser une classe Builder plutôt qu'une classe wrapper, mais la documentation sur le faire pour FXML est assez rare ou inexistante, donc je ne l'ai pas essayée. Par commodité, enveloppez le contenu html incorporé dans un CDATA construct. Ensuite, vous ne devez pas échapper à tous les caractères html et peuvent laisser <, >, et d'autres comme cela est plutôt que réencodage ces caractères &lt;, &gt;, etc.

Embedded WebView

embeddedwebview/embedded -webview.fxml

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.geometry.Insets?> 
<?import javafx.scene.layout.VBox?> 
<?import embeddedwebview.EmbeddedWebView?> 
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" 
     prefHeight="150.0" prefWidth="220.0"> 
    <padding> 
    <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> 
    </padding> 
    <EmbeddedWebView fx:id="embeddedWebView"> 
    <content> 
     <![CDATA[ 
     <h3>Embedded WebView</h3> 
     <p>HTML content inline in FXML</p> 
     ]]> 
    </content> 
    </EmbeddedWebView> 
</VBox> 

embeddedwebview/EmbeddedWebViewApp.java

package embeddedwebview; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Scene; 
import javafx.scene.layout.Pane; 
import javafx.stage.Stage; 

public class EmbeddedWebViewApp extends Application { 
    @Override 
    public void start(Stage stage) throws Exception { 
     FXMLLoader loader = new FXMLLoader(
       getClass().getResource(
         "embedded-webview.fxml" 
       ) 
     ); 
     Pane pane = loader.load(); 

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

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

embeddedwebview/EmbeddedWebView.java

import javafx.scene.layout.StackPane; 
import javafx.scene.web.WebView; 

/** 
* A WebView which has getters and setters for content or a document url. 
* 
* Usage in FXML element is: 
* 
* EITHER by specifying a url to a html document: 
* 
*  <EmbeddedWebView fx:id="embeddedWebView" url="/embeddedwebview/embedded.html"> 
*   
* OR by specifying CDATA escaped html content: 
* 
*  <EmbeddedWebView fx:id="embeddedWebView"> 
*   <content> 
*    <![CDATA[ 
*     <h3>Embedded WebView</h3> 
*     <p>HTML content inline in FXML</p> 
*    ]]> 
*   </content> 
*  </EmbeddedWebView> 
* 
*/ 
public class EmbeddedWebView extends StackPane { 

    final private WebView webView; 

    // For space efficiency, an alternate implementation could just 
    // rely on the content in the WebView itself rather than 
    // duplicating the content here, but it was simple to implement with a duplicate. 
    private String content; 

    private String url; 

    public EmbeddedWebView() { 
     webView = new WebView(); 
     getChildren().add(webView); 
    } 

    public String getContent() { 
     return content; 
    } 

    /** 
    * Loads html content directly into the webview. 
    * @param content a html content string to load into the webview. 
    */ 
    public void setContent(String content) { 
     this.content = content; 
     webView.getEngine().loadContent(content); 
    } 

    public String getUrl() { 
     return url; 
    } 

    /** 
    * Loads content into the WebView from a given url. 
    * The allowed url types are http, https and file. 
    * 
    * Additionally, content can be loaded from a classpath resource. 
    * To be loaded from the classpath, the url must start with a/character 
    * and specify the full resource path to the html 
    * (i.e., relative resource path specifiers are not allowed). 
    * 
    * @param url the location of the html document to be loaded. 
    */ 
    public void setUrl(String url) { 
     if (url == null || ! (url.startsWith("/") || url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:"))) { 
      throw new IllegalArgumentException("url must start with one of http: file: https: or /"); 
     } 

     this.url = url; 

     if (url.startsWith("/")) { 
      webView.getEngine().load(
        EmbeddedWebView.class.getResource(url).toExternalForm() 
      ); 
     } else { 
      webView.getEngine().load(
        url 
      ); 
     } 
    } 
} 

d'utilisation Autre référence à un document html.

remplacer l'élément dans la EmbeddedWebView FXML au-dessus de ce qui suit:

<EmbeddedWebView fx:id="embeddedWebView" url="/embeddedwebview/embedded.html"/> 

embeddedwebview/intégré.html

<!doctype html> 

<html lang="en"> 
<head> 
    <meta charset="utf-8"> 
</head> 

<body> 
    <h3>Embedded WebView</h3> 
    <p>HTML content inline in FXML</p> 
</body> 
</html> 

Ainsi, la fonction ne setUrl de définir l'URL global variabe qui getUrl retours?

Le membre URL est local au EmbeddedWebView plutôt que mondiale est portée à l'application, mais oui, vous avez l'idée générale, setURL() est un compositeur et FXML il semble par réflexion pour définir l'URL dans le EmbeddedWebView et vous pouvez récupérer l'URL de l'EmbeddedWebView à partir de n'importe quelle classe en utilisant la fonction publique getURL().

+0

Wow @jewelsea c'est une implémentation géniale et exactement ce que je cherchais. Merci d'être allé au-delà! Ainsi, la fonction setUrl définit-elle l'URL de variable globale que renvoie getUrl? C'est très créatif. – Maxwell

+0

Réponse mise à jour pour répondre à une question supplémentaire. – jewelsea