java之Jasper 报告组件在 JavaFX Swing 节点中未正确呈现

落叶无声 阅读:8 2024-06-20 12:54:19 评论:0

为了在 JavaFX 11 中创建 Jasper 报告,我使用了动态报告。我正在 Swing 节点内加载报告,但只有当我单击堆栈 Pane 区域和所有其他组件时才会出现 Jasper 报告,并且仅当我将鼠标悬停在所有这些组件上时才可见。组件和报告内容不会立即加载,而不是在鼠标悬停时显示,在堆栈 Pane 上滚动时会显示报告。

因为这是 bug在 Java 8 中似乎已解决,但在 Java 11 中我也遇到了同样的问题。

更新

由于我没有得到任何回应,并且按照 kleopatra 的建议,我创建了最少的可重现代码。请看看这个。

JavaFxJasperReportsDemo.java

package demo; 
 
import java.util.ArrayList; 
import java.util.List; 
 
import javax.swing.SwingUtilities; 
 
import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.embed.swing.SwingNode; 
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.AnchorPane; 
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; 
import net.sf.jasperreports.engine.JasperPrint; 
import net.sf.jasperreports.swing.JRViewer; 
 
public class JavaFxJasperReportsDemo extends Application{ 
 
    @FXML 
    private StackPane stackPane; 
 
    public void start(Stage stage) throws Exception{ 
 
        try{ 
            System.out.println("Hello"); 
            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 { 
            JasperPrint jasperPrintReport=report.toJasperPrint(); 
            SwingNode swingNode = new SwingNode(); 
            AnchorPane.setTopAnchor(swingNode,0.0); 
            AnchorPane.setBottomAnchor(swingNode,0.0); 
            AnchorPane.setLeftAnchor(swingNode,0.0); 
            AnchorPane.setRightAnchor(swingNode,0.0); 
            JRViewer jrViewer=   new JRViewer(jasperPrintReport); 
            SwingUtilities.invokeLater(() ->swingNode.setContent(jrViewer) 
                    ); 
            stackPane.getChildren().add(swingNode); 
        } catch (DRException e) { 
            e.printStackTrace(); 
        } 
 
    } 
 
    public static void main(String[] args){ 
        System.out.println("Hello Main"); 
        try{ 
            launch(args); 
        } 
        catch (Exception e){ 
            e.printStackTrace(); 
        } 
    } 
} 

演示POJO.java
package demo; 
 
public class DemoPOJO { 
 
    String name; 
 
    String city; 
 
    public String getName() { 
        return name; 
    } 
 
    public void setName(String name) { 
        this.name = name; 
    } 
 
    public String getCity() { 
        return city; 
    } 
 
    public void setCity(String city) { 
        this.city = city; 
    } 
} 

FXMLJavaFXJasperReportsDemo.fxml
<?xml version="1.0" encoding="UTF-8"?> 
 
<?import javafx.scene.control.Button?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.layout.AnchorPane?> 
<?import javafx.scene.layout.StackPane?> 
 
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="561.0" prefWidth="745.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="demo.JavaFxJasperReportsDemo"> 
   <children> 
      <Label layoutX="345.0" layoutY="24.0" text="Java FX Demo Application" /> 
      <StackPane fx:id="stackPane" layoutX="14.0" layoutY="120.0" prefHeight="392.0" prefWidth="722.0" /> 
      <Button layoutX="62.0" layoutY="68.0" mnemonicParsing="false" onAction="#loadReport" text="Load Report" /> 
   </children> 
</AnchorPane> 

我使用的依赖项是:-
<dependency> 
    <groupId>net.sourceforge.dynamicreports</groupId> 
    <artifactId>dynamicreports-core</artifactId> 
    <version>6.1.0</version> 
</dependency> 
 
<dependency> 
    <groupId>org.openjfx</groupId> 
    <artifactId>javafx-controls</artifactId> 
    <version>11</version> 
</dependency> 
 
<dependency> 
    <groupId>org.openjfx</groupId> 
    <artifactId>javafx-fxml</artifactId> 
    <version>11</version> 
</dependency> 
 
<dependency> 
    <groupId>javax.xml.bind</groupId> 
    <artifactId>jaxb-api</artifactId> 
    <version>2.2.11</version> 
</dependency> 
 
<dependency> 
    <groupId>org.openjfx</groupId> 
    <artifactId>javafx-swing</artifactId> 
    <version>11-ea+24</version> 
</dependency> 

输出
  • 单击加载报告按钮后,只有一个保存图标可见,没有报告可见。
  • 单击堆栈 Pane 区域后,现在可以看到报告。
  • 将鼠标悬停在另一个图标上后,现在可以看到打印图标。
  • 将鼠标悬停在其他图标上后,它们会一一可见。
  • 请您参考如下方法:

    在检查 OpenJDK wiki 后 OpenJFX debug flags你可以尝试跟随。

    添加在 pom.xml 的构建部分OpenJFX 的 JVM 选项

    <plugin> 
        <groupId>org.openjfx</groupId> 
        <artifactId>javafx-maven-plugin</artifactId> 
        <version>0.0.4</version> 
        <configuration> 
            <mainClass>demo.JavaFxJasperReportsDemo</mainClass> 
            <options> 
                <option>-Dprism.verbose=true</option> 
            </options> 
        </configuration> 
    </plugin> 
    

    使用 mvn javafx:run 执行应用程序它将报告检测到的 Prism 配置

    在我的系统上输出
    Prism pipeline init order: es2 sw  
    Using Double Precision Marlin Rasterizer 
    Using dirty region optimizations 
    Not using texture mask for primitives 
    Not forcing power of 2 sizes for textures 
    Using hardware CLAMP_TO_ZERO mode 
    Opting in for HiDPI pixel scaling 
    Prism pipeline name = com.sun.prism.es2.ES2Pipeline 
    Loading ES2 native library ... prism_es2 
        succeeded. 
    GLFactory using com.sun.prism.es2.X11GLFactory 
    (X) Got class = class com.sun.prism.es2.ES2Pipeline 
    Initialized prism pipeline: com.sun.prism.es2.ES2Pipeline 
    ... 
    Graphics Vendor: Intel Open Source Technology Center 
           Renderer: Mesa DRI Intel(R) Ivybridge Mobile  
            Version: 3.0 Mesa 19.3.2 
    

    它使用硬件加速渲染器 Loading ES2 native library ... prism_es2
    可以强制使用软件渲染器。 pom.xml的变化
            <options> 
                <option>-Dprism.verbose=true</option> 
                <option>-Dprism.order=sw</option 
            </options> 
    

    然后输出是
    Prism pipeline init order: sw  
    Using Double Precision Marlin Rasterizer 
    Using dirty region optimizations 
    Not using texture mask for primitives 
    Not forcing power of 2 sizes for textures 
    Using hardware CLAMP_TO_ZERO mode 
    Opting in for HiDPI pixel scaling 
    *** Fallback to Prism SW pipeline 
    Prism pipeline name = com.sun.prism.sw.SWPipeline 
    (X) Got class = class com.sun.prism.sw.SWPipeline 
    Initialized prism pipeline: com.sun.prism.sw.SWPipeline 
     vsync: true vpipe: false 
    

    它正在使用软件渲染器 Fallback to Prism SW pipeline .

    用于上述测试的版本:

    JDK
    java version "11.0.2" 2019-01-15 LTS 
    Java(TM) SE Runtime Environment 18.9 (build 11.0.2+9-LTS) 
    Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.2+9-LTS, mixed mode) 
    

    马文
    Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) 
    


    标签:java
    声明

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    关注我们

    一个IT知识分享的公众号