Reputation: 5311
I am working on a JavaFX project in which I have a bunch of static HTML&JS pages and I am loading the index.html
which the users can check out and click on links, etc.
Now, generally when we are using a browser like Firefox
or Chromium
, then calling the print command does the printing task.
BUt that is not the same thing happening in the webview
. How do I enable printing in JavaFX's webpage rendering mechanism.
What is also okay is some way to call a print function and pass it the webpage or webview from JavaScript.
Here is my code so far :
public class Main extends Application {
private Scene scene;
MyBrowser myBrowser;
@Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Test web");
Screen screen = Screen.getPrimary();
myBrowser = new MyBrowser();
scene = new Scene(myBrowser, 1080, 1920);
myBrowser.setPrefSize(1080, 1920);
Rectangle2D bounds = screen.getVisualBounds();
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
scene.setRoot(myBrowser);
primaryStage.setScene(scene);
primaryStage.setMaximized(false);
primaryStage.setFullScreen(true);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
class MyBrowser extends Region {
final String hellohtml = "hello.html";
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
public MyBrowser(){
URL urlHello = getClass().getResource("hello.html");
webEngine.load(urlHello.toExternalForm());
webView.setPrefSize(1080, 1920);
webView.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
@Override public void onChanged(Change<? extends Node> change) {
Set<Node> deadSeaScrolls = webView.lookupAll(".scroll-bar");
for (Node scroll : deadSeaScrolls) {
scroll.setVisible(true);
}
}
});
getChildren().add(webView);
}
}
Any suggestions or pointers would be nice. Thank you.. :-)
Upvotes: 0
Views: 1150
Reputation: 7506
Assuming you have something like this in the page in JS:
<script type="text/javascript">
function printInJava() {
...
}
</script>
Here is how you go about registering a bridge between your Java code and your JavaScript:
WebEngine webEngine = webView.getEngine();
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends State> ov, State t, State t1) {
if (t1 == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("app", this);
}
}
});
And in the same class you have the method you want to trigger from JavaScript:
public void print() {
print(webView);
}
The method print(Node)
is the same as from this example. I must confess however, that I did not actually try that code and from the look on it you might run into some issues with scaling and printing on multiple pages.
Now you can simply complete the JavaScript:
function printInJava() {
app.print(); // call out the Java print method defined on the register variable app
}
When putting all this together you end up with this code:
import javafx.application.Application;
import javafx.collections.ListChangeListener;
import javafx.concurrent.Worker;
import javafx.print.PageLayout;
import javafx.print.PageOrientation;
import javafx.print.Paper;
import javafx.print.Printer;
import javafx.print.PrinterJob;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.Region;
import javafx.scene.transform.Scale;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
import java.net.URL;
import java.util.Set;
public class Main extends Application {
private Scene scene;
MyBrowser myBrowser;
@Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Test web");
myBrowser = new MyBrowser();
scene = new Scene(myBrowser, 1080, 1920);
primaryStage.setScene(scene);
primaryStage.setFullScreen(true);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
class MyBrowser extends Region {
final String hellohtml = "index.html";
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
public MyBrowser(){
URL urlHello = getClass().getResource(hellohtml);
webEngine.load(urlHello.toExternalForm());
webView.setPrefSize(1080, 1920);
webView.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
@Override public void onChanged(Change<? extends Node>
change) {
Set<Node> deadSeaScrolls = webView.lookupAll(".scroll-bar");
for (Node scroll : deadSeaScrolls) {
scroll.setVisible(true);
}
}
});
webEngine. getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
if (newValue == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("app", this);
} });
getChildren().add(webView);
}
/**
* Callback function from the JavaScript code.
*/
public void print() {
print(webView);
}
/** Scales the node based on the standard letter, portrait paper to be printed.
* @param node The scene node to be printed.
*/
public void print(final Node node) {
Printer printer = Printer.getDefaultPrinter();
PageLayout pageLayout = printer.createPageLayout(Paper.NA_LETTER, PageOrientation.PORTRAIT, Printer.MarginType.DEFAULT);
double scaleX = pageLayout.getPrintableWidth() / node.getBoundsInParent().getWidth();
double scaleY = pageLayout.getPrintableHeight() / node.getBoundsInParent().getHeight();
node.getTransforms().add(new Scale(scaleX, scaleY));
PrinterJob job = PrinterJob.createPrinterJob();
if (job != null) {
boolean success = job.printPage(node);
if (success) {
job.endJob();
}
}
}
}
Further references:
Upvotes: 1