JavaFX与Swing渲染

JavaFX与Swing渲染,swing,javafx,Swing,Javafx,我使用Swing和JavaFX将图像渲染到屏幕上,但得到了意外的计时:目的只是在组件上的随机位置渲染1000000个图像。为什么JavaFX要花这么长时间 结果:摆动:2.5秒。JavaFX8.5秒。代码如下。 在JavaFX中 public class JFXTest extends Application { public static void main(String[] args) { launch(args); } @Override public void start(St

我使用Swing和JavaFX将图像渲染到屏幕上,但得到了意外的计时:目的只是在组件上的随机位置渲染1000000个图像。为什么JavaFX要花这么长时间

结果:摆动:2.5秒。JavaFX8.5秒。代码如下。

在JavaFX中

public class JFXTest extends Application
{
public static void main(String[] args)
{
    launch(args);
}

@Override
public void start(Stage theStage)
{
    Group root = new Group();
    Scene theScene = new Scene( root );
    theStage.setScene( theScene );

    Canvas canvas = new Canvas( 1000, 1000);
    root.getChildren().add( canvas );

    GraphicsContext gc = canvas.getGraphicsContext2D();

    new ResourceLoaderJFX();
    System.out.println("Running test");

    Random ran = new Random();

    ClassLoader classLoader = getClass().getClassLoader();
    URL url = classLoader.getResource("sky.png");
    Image image = new Image(url.toString());
    long t1 = System.nanoTime();
    for (int j=0; j<1000000; j++ ) {
        int x = ran.nextInt(1000);
        int y = ran.nextInt(1000);
        gc.drawImage(image, x, y);
    }
    System.out.println("\n");
    long t2 = System.nanoTime()-t1;
    System.out.println("Took " + (t2/1000000000.0) + " secs");
    System.out.println("Done");

    theStage.show();
}
}

Prism pipeline init order: d3d sw 
Using native-based Pisces 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.d3d.D3DPipeline
Loading D3D native library ...
D3DPipelineManager: Created D3D9Ex device
    succeeded.
Direct3D initialization succeeded
(X) Got class = class com.sun.prism.d3d.D3DPipeline
Initialized prism pipeline: com.sun.prism.d3d.D3DPipeline
OS Information:
Maximum supported texture size: 8192
    Windows version 10.0 build 14393
Maximum texture size clamped to 4096
D3D Driver Information:
    Intel(R) Iris(TM) Graphics 540
    \\.\DISPLAY2
    Driver igdumdim64.dll, version 20.19.15.4463
    Pixel Shader version 3.0
    Device : ven_8086, dev_1926, subsys_00151414
    Max Multisamples supported: 4
 vsync: true vpipe: true
Running test
public类JFXTest扩展应用程序
{
公共静态void main(字符串[]args)
{
发射(args);
}
@凌驾
公共空间开始(舞台)
{
组根=新组();
场景场景=新场景(根);
第三阶段:设置场景(场景);
画布=新画布(10001000);
root.getChildren().add(画布);
GraphicsContext gc=canvas.getGraphicsContext2D();
新的ResourceLoaderJFX();
System.out.println(“运行测试”);
Random ran=新的Random();
ClassLoader ClassLoader=getClass().getClassLoader();
URL=classLoader.getResource(“sky.png”);
Image Image=新图像(url.toString());
long t1=System.nanoTime();

对于(int j=0;j您在这里比较苹果和啤酒。在Swing中,当您调用drawImage时,图像实际上是渲染的。在JavaFX中,绘制图像的命令只是添加到命令缓冲区中,稍后将执行。

我想您正在经历的是JavaFX的保留模式和Swin的立即模式之间的差异g、 Swing从字面上来说就是把这些图像放到屏幕上,然后移动到下一个blitting位置。当它需要再次绘制它们时,它会从头开始。事实上,这是非常快的

JavaFX每次调用
drawImage
(请参见
GraphicsContext.writeImage()
)时都会创建一个不同的对象,然后将这些
对象保留在它从
Canvas
抓取的内部缓冲区中。除此之外,它还会创建六个双对象,并将它们放入完全相同的缓冲区中(请参见
GraphicsContext.updateTransform()

JavaFX的销售是它的保留模式。它允许你在屏幕上操作它的
节点
s,就好像它们在二维(实际上是三维)坐标系中一样,它将“免费”完成这项工作。如果你想在二维场景中定位对象并移动它们,这是非常强大的,因为游戏程序员都知道这一点

您为此付出的代价是,场景比Swing中相应的场景要重得多,并且图像的内存成本在JavaFX应用程序中是累积的。在JavaFX应用程序中,您有一个
场景
,您正在添加一个
画布
,它正在创建场景图。Swing没有这样做


如果您在探查器中运行程序,您可以确切地看到花费的时间,如果您在调试器中运行程序,您可以看到
画布
缓冲区的大小。

在您的代码中,JavaFX渲染1000K图像,而Swing只渲染10K图像。请为这两个示例提供一个示例,以便我们了解您的测试是正确的。感谢您指出错误:为了可读性,我对代码进行了向下编辑。我检查了示例中的数字,结果都是正确的。请提供完整的测试代码(以SSCCE的形式),这样我们就可以了解您的测试是否正确JavaFX:您似乎正在计时
ResourceLoaderJFX
;在进行测试时关注它的方法。Swing:替代
getGraphics()
,重写
paintComponent()
public class SwingTest extends JPanel {

public void init() {
    setVisible(true);
}

public void runTest() {
    System.out.println("Running test");
    BufferedImage bufferedImage=null;
    try {
        bufferedImage = ImageIO.read(new File("C:\\Users\\resources\\png\\sky.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
    long t1 = System.nanoTime();
    Random ran = new Random();
    for (int j=0; j<(1000000); j++ ) {
        int x = ran.nextInt(1000);
        int y = ran.nextInt(1000);
        this.getGraphics().drawImage(bufferedImage, x, y, null);
    }
    long t2 = System.nanoTime()-t1;
    System.out.println("Took " + (t2/1000000000.0) + " secs");
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            JFrame f = new JFrame();
            SwingTest view= new SwingTest();
            view.init();
            f.add(worldViewPanel);
            f.pack();
            f.setSize(new Dimension(1000,1000));
            f.setVisible(true);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            view.runTest();
        }
    });
}
}

Connected to the target VM, address: '127.0.0.1:53764', transport: 'socket'