For creating Jasper Report in JavaFX 11 I am using dynamic reports. When I click on button Jasper Report open and visible inside a popup. But I can click the button as many number of times as I want and the report will open those number of times. But I want to lock parent window once the jasper report is visible so that the parent window is reachable only after closing the popup. The same thing we can achieve in Parent and Child Window as explained in this question but I want to achieve similar thing with Parent as my stage and child being a Jasper Window. Code for the same is mentioned below:-
JavaFxJasperReportsDemo.java
package demo;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import net.sf.dynamicreports.jasper.builder.JasperReportBuilder;
import net.sf.dynamicreports.report.builder.DynamicReports;
import net.sf.dynamicreports.report.builder.column.Columns;
import net.sf.dynamicreports.report.builder.component.Components;
import net.sf.dynamicreports.report.builder.datatype.DataTypes;
import net.sf.dynamicreports.report.constant.HorizontalTextAlignment;
import net.sf.dynamicreports.report.exception.DRException;
public class JavaFxJasperReportsDemo extends Application{
@FXML
private StackPane stackPane;
public void start(Stage stage) throws Exception{
try{
Parent root = FXMLLoader.load(getClass().getResource("/FXMLJavaFXJasperReportsDemo.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Java FX Demo");
stage.show();
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent arg0) {
Platform.exit();
}
});
}
catch (Exception e){
throw e;
}
}
@FXML
public void loadReport(ActionEvent event) {
JasperReportBuilder report = DynamicReports.report();
List<DemoPOJO> lstDemoPOJOs=new ArrayList<DemoPOJO>();
DemoPOJO demoPOJO=new DemoPOJO();
demoPOJO.setName("ABC");
demoPOJO.setCity("Delhi");
lstDemoPOJOs.add(demoPOJO);
demoPOJO = new DemoPOJO();
demoPOJO.setName("XYZ");
demoPOJO.setCity("Agra");
lstDemoPOJOs.add(demoPOJO);
report
.columns(
Columns.columnRowNumberColumn("S No"),
Columns.column("Name", "name", DataTypes.stringType()),
Columns.column("Address", "city", DataTypes.stringType())
).title(
Components.text("Demo Java Fx Jasper Reports").
setHorizontalTextAlignment(HorizontalTextAlignment.CENTER))
.pageFooter(Components.pageXofY())
.setDataSource(lstDemoPOJOs);
try {
report.show(false);
} catch (DRException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
try{
launch(args);
}
catch (Exception e){
e.printStackTrace();
}
}
}
As of now I don't have a solution based on "reachability" of parent window. But I can provide you an alternate solution to not allow the user to click multiple times. The idea is to disable the scene's root node as soon as you press the button and enabling it only when the report window is closed. Not sure whether this fits your purpose.
reportButton.setOnAction(e -> {
// Get root node of the scene
Node sceneRoot = ((Node)e.getTarget()).getScene().getRoot();
// First things first, disable it !!
sceneRoot.setDisable(true);
// Your actual method for showing report
loadReport(e);
// Get all current AWT windows.
java.awt.Window[] windows = java.awt.Window.getWindows();
// Get the recently added window (your report window) and add a close listener.
windows[windows.length-1].addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
// When the window is closed, enable your root node.
sceneRoot.setDisable(false);
}
});
});
Note: The internal implementation of JasperReportBuilder's JasperViewer is a JFrame.
[UPDATE]
Complete working demo below:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import net.sf.dynamicreports.jasper.builder.JasperReportBuilder;
import net.sf.dynamicreports.report.builder.DynamicReports;
import net.sf.dynamicreports.report.builder.column.Columns;
import net.sf.dynamicreports.report.builder.component.Components;
import net.sf.dynamicreports.report.builder.datatype.DataTypes;
import net.sf.dynamicreports.report.constant.HorizontalAlignment;
import net.sf.dynamicreports.report.exception.DRException;
import java.util.ArrayList;
import java.util.List;
public class JavaFxJasperReportsDemo extends Application {
@FXML
private StackPane stackPane;
public void start(Stage stage) throws Exception {
try {
StackPane root = new StackPane();
ContextMenu cm = new ContextMenu();
cm.getItems().addAll(new MenuItem("Test1"), new MenuItem("Test2"));
Button reportButton = new Button("Report");
reportButton.setContextMenu(cm);
reportButton.setOnAction(e -> {
// Get root node of the scene
Node sceneRoot = ((Node) e.getTarget()).getScene().getRoot();
// First things first, disable it !!
sceneRoot.setDisable(true);
// Your actual method for showing report
loadReport(e);
// Get all current AWT windows.
java.awt.Window[] windows = java.awt.Window.getWindows();
// Get the recently added window (your report window) and add a listener.
windows[windows.length - 1].addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
// When the window is closed, enable your root node.
sceneRoot.setDisable(false);
}
});
});
root.getChildren().add(reportButton);
Scene scene = new Scene(root, 200, 200);
stage.setScene(scene);
stage.setTitle("Java FX Demo");
stage.show();
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent arg0) {
Platform.exit();
}
});
} catch (Exception e) {
throw e;
}
}
@FXML
public void loadReport(ActionEvent event) {
JasperReportBuilder report = DynamicReports.report();
List<DemoPOJO> lstDemoPOJOs = new ArrayList<DemoPOJO>();
DemoPOJO demoPOJO = new DemoPOJO();
demoPOJO.setName("ABC");
demoPOJO.setCity("City 1");
lstDemoPOJOs.add(demoPOJO);
demoPOJO = new DemoPOJO();
demoPOJO.setName("XYZ");
demoPOJO.setCity("City 2");
lstDemoPOJOs.add(demoPOJO);
report
.columns(
Columns.columnRowNumberColumn("S No"),
Columns.column("Name", "name", DataTypes.stringType()),
Columns.column("Address", "city", DataTypes.stringType())
).title(
Components.text("Demo Java Fx Jasper Reports").
setHorizontalAlignment(HorizontalAlignment.CENTER))
//.pageFooter(Components.pageXofY())
.setDataSource(lstDemoPOJOs);
try {
report.show(false);
} catch (DRException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
launch(args);
} catch (Exception e) {
e.printStackTrace();
}
}
}