Skip to content Skip to sidebar Skip to footer

Size Javafx Webview To The Minimum Size Needed By The Document Body

I'm writing a custom dialog in JavaFX for my project. I need a variant but quick mode for showing the dialog content. I know about controlsFX; actually I'm using it but I want to s

Solution 1:

Automated sizing support of WebView is covered by a feature request in the JavaFX issue tracker:

The feature request has currently not been implemented or scheduled for implementation. You can vote for or comment on the feature request.

There is no work-around that I know of. Earlier version of WebView seemed to work with the following code engine.executeScript("document.width") and engine.executeScript("document.height"). But these commands no longer worked last time I tried them.

Solution 2:

Until automatic preferred sizing is implemented, a certain blogmeister has come up with a solution that seems to work (for now).

It can be found in its original form on his website.

It makes having a preferred-size WebView as easy as

WebViewFitContent webViewFitContent = new WebViewFitContent(html);
yourContainer.getChildren().add(webViewFitContent);

WebViewFitContent in action


In case the link were to ever die,

WebViewFitContent.java

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.concurrent.Worker.State;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.layout.Region;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import netscape.javascript.JSException;

import java.util.Set;

public final classWebViewFitContentextendsRegion {

    final WebView webview = newWebView();
    final WebEngine webEngine = webview.getEngine();

    publicWebViewFitContent(String content) {
        webview.setPrefHeight(5);

        widthProperty().addListener(newChangeListener<Object>() {
            @Overridepublicvoidchanged(ObservableValue<?> observable, Object oldValue, Object newValue) {
                Double width = (Double)newValue;
                webview.setPrefWidth(width);
                adjustHeight();
            }
        });

        webview.getEngine().getLoadWorker().stateProperty().addListener(newChangeListener<State>() {
            @Overridepublicvoidchanged(ObservableValue<? extends State> arg0, State oldState, State newState)         {
                if (newState == State.SUCCEEDED) {
                    adjustHeight();
                }
            }
        });

        webview.getChildrenUnmodifiable().addListener(newListChangeListener<Node>() {
            @OverridepublicvoidonChanged(ListChangeListener.Change<? extends Node> change) {
                Set<Node> scrolls = webview.lookupAll(".scroll-bar");
                for (Node scroll : scrolls) {
                    scroll.setVisible(false);
                }
            }
        });

        setContent(content);
        getChildren().add(webview);
    }

    publicvoidsetContent(final String content) {
        Platform.runLater(newRunnable(){
            @Overridepublicvoidrun() {
                webEngine.loadContent(getHtml(content));
                Platform.runLater(newRunnable(){
                    @Overridepublicvoidrun() {
                        adjustHeight();
                    }
                });
            }
        });
    }


    @OverrideprotectedvoidlayoutChildren() {
        double w = getWidth();
        double h = getHeight();
        layoutInArea(webview,0,0,w,h,0, HPos.CENTER, VPos.CENTER);
    }

    privatevoidadjustHeight() {
        Platform.runLater(newRunnable(){
            @Overridepublicvoidrun() {
                try {
                    Object result = webEngine.executeScript(
                            "var myDiv = document.getElementById('mydiv');" +
                                    "if (myDiv != null) myDiv.offsetHeight");
                    if (result instanceofInteger) {
                        Integer i = (Integer) result;
                        double height = newDouble(i);
                        height = height + 20;
                        webview.setPrefHeight(height);
                    }
                } catch (JSException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    privateStringgetHtml(String content) {
        return"<html><body>" +
                "<div id=\"mydiv\">" + content + "</div>" +
                "</body></html>";
    }

}

Note 1: In the above I added a null-check in the javascript and chose to print out any exceptions that might occur instead of ignoring them.

Note 2: Sometimes the WebView's content doesn't show through. If anyone else experiences this please leave a comment.

Solution 3:

This is a very late answer.

You have to apply ChangeListener on the document, before calulating the height. Kindly find a running example to your question at: Correct sizing of Webview embedded in Tabelcell

However my experience is that the high is still sometimes to big.

Post a Comment for "Size Javafx Webview To The Minimum Size Needed By The Document Body"