Jasper Reports组件在JavaFX Swing节点中无法正确渲染

13

为了在JavaFX 11中创建Jasper报表,我正在使用dynamic reports。我将报表加载到Swing Node内,但是只有当我单击堆栈窗格区域时,Jasper报表才会出现,并且只有当我悬停在所有这些组件上时,所有其他组件才可见。与其它内容一样,组件和报表内容并非立即加载,而是在鼠标悬停时显示,当滚动堆栈窗格时,报表才会显示。

由于这是Java 8中的错误(bug),似乎已得到解决,但在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();
        }
    }
}

DemoPOJO.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

->

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>

输出

  1. 点击“加载报告”按钮后,只有一个保存图标可见,没有报告可见。 点击“加载报告”按钮后,只有一个保存图标可见,没有报告可见。

  2. 点击堆栈窗格区域后,现在报告可见。 点击堆栈窗格区域后,现在报告可见。

  3. 经过悬停在其他图标上后,现在打印图标可见。 经过悬停在其他图标上后,现在打印图标可见。

  4. 经过悬停在其他图标上后,它们一个接一个地变得可见。 经过悬停在其他图标上后,它们一个接一个地变得可见。


我只是得到了赞,但没有人给我答案。我非常渴望得到这个问题的任何解决方案。 - Satish Pahuja
3
提供一个 [mcve](注意,不是整个代码,而是一个仅用于演示您问题的小例子)可能会提高您获得答案的机会 :)。建议您这样做。 - kleopatra
2
也许来自Swing/JasperReport的人可以提供一些有用的见解。 - kleopatra
1
嗨,我使用 jbsdk11b125_osx_x64 运行程序,但无法重现问题。它直接显示完整的内容。尽管我收到了一个警告:“使用 JavaFX API 版本 11.0.1 加载 FXML 文档,JavaFX 运行时版本为 10.0.2-internal...” - Vall0n
2
  1. 这可能也与显卡驱动程序有关。可以参考以下一些属性作为故障排除的起点:https://docs.oracle.com/en/java/javase/11/troubleshoot/java-2d-properties.html。 2) 是否尝试过较新版本的org.openjfx:javafx-swing,例如11? 3)使用Java 11.0.5,Maven 3.6.2和插件org.openjfx:javafx-maven-plugin:0.0.4可避免渲染问题(在单击“Load Report”按钮后会显示报告)。该应用程序是通过mvn clean javafx:run启动的。
- SubOptimal
显示剩余18条评论
2个回答

1

在查看OpenJDK wiki上的OpenJFX调试标志后,您可以尝试以下操作。

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)

Maven
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)

谢谢分享,但这种方法并没有解决问题。 - Satish Pahuja
1
@SatishPahuja,你使用的具体Java版本是什么java -version?你尝试过运行插件org.openjfx:javafx-swing的发布版11而不是11-ea+24吗? - SubOptimal

0

我也遇到了类似的问题,但是通过将以下Maven依赖项添加到我的项目中,我解

<dependency>
    <groupId>win.zqxu</groupId>
    <artifactId>jrviewer-fx</artifactId>
    <version>0.1.1</version>

</dependency>

这里是实现它的代码部分

        JRViewerFX viewer = new JRViewerFX(jasperprint_report);        

              Platform.runLater(new Runnable() {
                  @Override
                  public void run() {

                      report_scroll_pane.setContent(viewer);
                  }
              });

我们在JavaFx应用程序的SwingNode中使用Qoppa PDF Viewer时遇到了类似的问题。在Java8中一切正常,但当我们切换到OpenFx11(11.0.7)时,它在Windows10和MacOs机器上停止正常工作。但是当我们将OpenFx更新为OpenFX11 LTS (11.0.8)时,这个错误在MacOs上消失了,但仍存在于Windows机器上。所以我的问题是,你们在Windows上解决这个问题了吗? - trisek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接