Setting custom CSS rules using JavaScript in JavaFX WebView
I am using WebView
full screen to display fixed size content 1024x768
, so I need to scale it so that it stretches from top to bottom. To do this, I have installed the following code in my controller initialize()
:
this.wv.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
public void changed(ObservableValue<? extends State> ov, State oldState, State newState)
{
if (newState == State.SUCCEEDED)
{
wv.requestFocus();
wv.getEngine().setUserStyleSheetLocation(getClass().getResource("/css/user.css").toExternalForm());
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
Element maincontainer = (Element) wv.getEngine().executeScript("document.getElementById('pbody')");
maincontainer.setAttribute("style", String.format("-webkit-transform: scale(%.5f)", (primaryScreenBounds.getHeight() / 768.0)));
}
else if (newState == State.FAILED)
{
//.
}
}
});
The CSS user.css
loads fine and here is the code for reference:
body {
overflow-x: hidden;
background-color: #ccc;
}
#pbody {
margin: 0 auto;
-webkit-transform-origin: top center;
}
In HTML, the body tag definitely has an id:
<body id="pbody">
The problem is the #pbody
javascript bit not found for some reason , so the following error occurs:
java.lang.NullPointerException
at com.mediacitizens.companyapp.presentation.desktop.SlideshowController$1.changed(SlideshowController.java:165)
at com.mediacitizens.companyapp.presentation.desktop.SlideshowController$1.changed(SlideshowController.java:1)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:195)
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:161)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:130)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:163)
at javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:975)
at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1086)
at javafx.scene.web.WebEngine$LoadWorker.access$600(WebEngine.java:968)
at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:955)
at com.sun.webpane.platform.WebPage.fireLoadEvent(WebPage.java:2372)
at com.sun.webpane.platform.WebPage.fwkFireLoadEvent(WebPage.java:2220)
at com.sun.webpane.webkit.network.URLLoader.twkDidFinishLoading(Native Method)
at com.sun.webpane.webkit.network.URLLoader.access$1300(URLLoader.java:42)
at com.sun.webpane.webkit.network.URLLoader$6.run(URLLoader.java:657)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Thread.java:722)
SlideshowController.java:165
is the line:
maincontainer.setAttribute("style", String.format("-webkit-transform: scale(%.5f)", (primaryScreenBounds.getHeight() / 768.0)));
I cannot understand the reason for this behavior.
Refresh . I tried to wait for the document to load, but it doesn't work either. I first posted this manually in the content:
<script>
function scaleBody(scale)
{
alert(3);
document.getElementById('pbody').style.webkitTransform = "scale("+scale+")";
}
</script>
and then using a state change listener:
double scale = Screen.getPrimary().getVisualBounds().getHeight() / 768.0;
wv.getEngine().executeScript(String.format("alert(1); window.onload = function(){ alert(2); scaleBody(%.5f); }", scale));
Only alert(1)
works and no errors are generated ...
... don't know yet how to execute js in JavaFX.
source to share
You need to provide more details about what html content you are trying to load. Here is my test code that works fine as expected:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Screen;
import javafx.stage.Stage;
import org.w3c.dom.Element;
public class WVTest extends Application {
private WebView wv;
@Override
public void start(Stage primaryStage) {
wv = new WebView();
wv.getEngine().load(this.getClass().getResource("index.html").toExternalForm());
// wv.getEngine().load("http://www.oracle.com/products/index.html");
wv.getEngine().getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
@Override
public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
wv.requestFocus();
wv.getEngine().setUserStyleSheetLocation(getClass().getResource("style.css").toExternalForm());
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
Element maincontainer = (Element) wv.getEngine().executeScript("document.getElementById('pbody')");
System.out.println("maincontainer = " + maincontainer);
maincontainer.setAttribute("style", String.format("-webkit-transform: scale(%.5f)", (primaryScreenBounds.getHeight() / 768.0)));
}
}
});
VBox root = new VBox();
root.getChildren().addAll(wv);
Scene scene = new Scene(root, 300, 250);
scene.getStylesheets().add(this.getClass().getResource("style.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
with style.css
body {
overflow-x: hidden;
background-color: #ccc;
}
#pbody {
margin: 0 auto;
-webkit-transform-origin: top center;
}
and index.html
<html>
<head>
<title>Test</title>
</head>
<body id="pbody">
Test<br/>
Test<br/>
Test<br/>
Test<br/>
</body>
</html>
Line
System.out.println("maincontainer = " + maincontainer);
prints
maincontainer = [HTMLBodyElement object]
Alternatively open the html content you load in a normal web browser, then press F12 (firebug or similar tool) and in the JS console, enter document.getElementById('pbody')
.
source to share