当 Jasper Report 在弹出窗口中可见时如何在 JavaFx 中锁定 Parent Window
How to lock Parent Window in JavaFx when Jasper Report is visible in popup
为了在 JavaFX 11 中创建 Jasper Report,我使用的是动态报告。当我单击按钮时,Jasper Report 打开并在弹出窗口中可见。但是我可以根据需要多次单击该按钮,报告将打开这些次数。但是我想在 jasper 报告可见后锁定 parent window,以便只有在关闭弹出窗口后才能访问 parent window。我们可以在 Parent 和 Child Window 中实现同样的事情,如 question 中所述,但我想用 Parent 作为我的舞台和 child 成为碧玉 Window。下面提到了相同的代码:-
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();
}
}
}
截至目前,我还没有基于父 window 的“可达性”的解决方案。但我可以为您提供另一种解决方案,不允许用户多次点击。这个想法是在您按下按钮后立即禁用场景的根节点,并仅在报告 window 关闭时启用它。不确定这是否符合您的目的。
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);
}
});
});
注:JasperReportBuilder的JasperViewer内部实现是一个JFrame。
[更新]
下面是完整的工作演示:
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();
}
}
}
这是对 Sai Dandem 发布的内容的修改代码。它将禁用所有打开的 javafx windows 并且 jasper 查看器将始终位于顶部。当 jasper viewer 关闭时,所有 windows 将被启用。
public class MakeJasperViewerAsModalWindow {
public MakeJasperViewerAsModalWindow(JasperViewer jasperViewer) {
jasperViewer.setAlwaysOnTop(true);
final java.awt.Window[] windows = java.awt.Window.getWindows();
final List<Window> windowsfx = Window.getWindows();
windowsfx.stream().forEach(o -> {
o.getScene().getRoot().setDisable(true);
});
windows[windows.length - 1].addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent evt) {
windowsfx.stream().forEach(o -> {
o.getScene().getRoot().setDisable(false);
});
}
});
}
}
可以用作new MakeJasperViewerAsModalWindow(jasperViewer);
为了在 JavaFX 11 中创建 Jasper Report,我使用的是动态报告。当我单击按钮时,Jasper Report 打开并在弹出窗口中可见。但是我可以根据需要多次单击该按钮,报告将打开这些次数。但是我想在 jasper 报告可见后锁定 parent window,以便只有在关闭弹出窗口后才能访问 parent window。我们可以在 Parent 和 Child Window 中实现同样的事情,如 question 中所述,但我想用 Parent 作为我的舞台和 child 成为碧玉 Window。下面提到了相同的代码:-
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();
}
}
}
截至目前,我还没有基于父 window 的“可达性”的解决方案。但我可以为您提供另一种解决方案,不允许用户多次点击。这个想法是在您按下按钮后立即禁用场景的根节点,并仅在报告 window 关闭时启用它。不确定这是否符合您的目的。
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);
}
});
});
注:JasperReportBuilder的JasperViewer内部实现是一个JFrame。
[更新]
下面是完整的工作演示:
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();
}
}
}
这是对 Sai Dandem 发布的内容的修改代码。它将禁用所有打开的 javafx windows 并且 jasper 查看器将始终位于顶部。当 jasper viewer 关闭时,所有 windows 将被启用。
public class MakeJasperViewerAsModalWindow {
public MakeJasperViewerAsModalWindow(JasperViewer jasperViewer) {
jasperViewer.setAlwaysOnTop(true);
final java.awt.Window[] windows = java.awt.Window.getWindows();
final List<Window> windowsfx = Window.getWindows();
windowsfx.stream().forEach(o -> {
o.getScene().getRoot().setDisable(true);
});
windows[windows.length - 1].addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent evt) {
windowsfx.stream().forEach(o -> {
o.getScene().getRoot().setDisable(false);
});
}
});
}
}
可以用作new MakeJasperViewerAsModalWindow(jasperViewer);