JavaFX在FXML文档中编辑WebView [英] JavaFX edit WebView in FXML document

查看:265
本文介绍了JavaFX在FXML文档中编辑WebView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是能够使用控制器类将html内容放入fxml文档中的WebView对象。我的FXML文档中还有其他对象,如按钮和图像,我希望WebView只是GUI的一部分。我可以使用控制器类将内容放在FXML文档中的TextArea中。为WebView执行此操作有点棘手,因为它需要WebEngine才能使用它。我知道如何在没有FXML文档的情况下自行启动WebView,但是有人知道我的目标是否可以实现吗?

My goal is to be able to put html content into a WebView object in the fxml document using the controller class. My FXML document has other objects in it like buttons and images, I want the WebView just to be part of the GUI. I can put content inside a TextArea in the FXML document using the controller class. Doing this for WebView is a bit more tricky because it requires a WebEngine to go along with it. I know how to launch a WebView by itself without am FXML doc but does anyone know if my goal is achievable?

这是我在控制器类中的尝试,但我得到了调用目标异常:

This is my attempt in the controller class, but I get an invocation target exception:

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();
    }     

}


推荐答案

这是一种简洁的概念(至少如果我明白你在问什么:-)。我喜欢这个。感谢它的思考。

This is a kind of neat concept (at least if I understood what you are asking :-). I like this. Kudos for thinking of it.

在重新阅读你的问题时,我可能完全误解了它...如果是这样,我猜你可以忽略我的答案。

In re-reading your question, I may have completely misunderstood it... if so, I guess you can disregard my answer.

在FXML中内联指定HTML内容

不幸的是,WebView是最终的,所以你不能只将WebView扩展到将内容加载方法添加到可以在FXML中指定的元素。

Unfortunately, WebView is final, so you can't just extend WebView to add content loading methods to an element which can be specified in FXML.

解决方案是在WebView周围提供一个小包装类,FXML可以实例化并设置内容。我选择让包装类继承StackPane,这样包装器就是一个Node,可以在FXML中实例化,无论你想在哪里使用Node。

The solution is to provide a small wrapper class around the WebView that FXML can instantiate and set content into. I chose to have the wrapper class inherit StackPane, so that the wrapper is a Node and can be instantiated in FXML wherever you might want to use a Node.

你可能是能够使用Builder类而不是像我这样的包装类,但是对于FXML这样做的文档非常缺乏,所以我没有尝试过。

You might be able to use a Builder class rather than a wrapper class like I have, but documentation on doing that for FXML is pretty scarce to nonexistent, so I didn't try it.

为方便起见,将嵌入的html内容包装在 CDATA构造中。然后你不必转义所有的html字符,可以保留< > ,以及其他人而不是将这些字符重新编码为& lt; & gt; 等。

As a convenience, wrap the embedded html content in a CDATA construct. Then you don't have to escape all the html characters and can leave <, >, and others as is rather than re-encoding those characters as &lt;, &gt;, etc.

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
            );
        }
    }
}

备用使用参考一个html文档。

用以下内容替换上面fxml中的EmbeddedWebView元素:

Replace the EmbeddedWebView element in the above fxml with the following:

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

embeddedwebview / embedded.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>




setUrl函数是否设置了getUrl返回的全局变量url?

So does the setUrl function set the global variabe url which getUrl returns?

url成员是EmbeddedWebView的本地成员,而不是应用程序的全局范围,但是,你有一般的想法, setURL()是一个setter,FXML通过反射来查找它,以便在EmbeddedWebView中设置url,然后你可以使用public从任何类中检索来自EmbeddedWebView的url code> getURL()功能。

The url member is local to the EmbeddedWebView rather than global is scope to the application, but yes, you have the general idea, setURL() is a setter and FXML looks it up by reflection to set the url in the EmbeddedWebView and you can latter retrieve the url out of the EmbeddedWebView from any class using the public getURL() function.

这篇关于JavaFX在FXML文档中编辑WebView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆