当前位置: 首页 > 知识库问答 >
问题:

JavaFX与Swing呈现

张建华
2023-03-14

我使用Swing和JavaFX将图像呈现到屏幕上,但得到了意想不到的时间:目标只是在组件上的随机位置呈现1,000,000个图像。为什么JavaFX花了这么长时间?

结果:摆动2.5秒。JavaFX 8.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

用了8.230974466秒

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'

JAVAFX花费了0.02173174秒@10,000个映像,第二次运行花费了0.018200605秒

SWING用了0.138639497秒@10,000个图像,第二次运行用了0.13744251秒

共有1个答案

呼延聪
2023-03-14

我认为您正在体验的是JavaFX的保留模式和Swing的即时模式之间的区别。Swing是字面上取下这些图像并将它们弹到屏幕上,然后移动到下一个弹出位置。当它需要再次绘制它们时,它从头开始。碰巧,这是非常快的。

每次调用DrawImage(请参见GraphicsContext.writeImage())时,JavaFX都会创建一个不同的对象,然后将这些对象保留在它从Canvas获取的内部缓冲区中。在此基础上,它创建了六个double,并将它们放入完全相同的缓冲区(请参见GraphicsContext.updateTransform())。

JavaFX的卖点是它的保留模式。它将允许您在屏幕上操作它的节点,就像它们在二维(实际上是三维)坐标系中一样,并且它将“免费”地这样做。如果你想在2-D场景中定位物体并移动它们,这是非常强大的,正如游戏程序员很清楚的那样。

您为此付出的代价是场景比Swing中的相应场景要沉重得多,并且图像的内存开销在JavaFX应用程序中是累积的。在JavaFX应用程序中,您有一个scene,您要向其添加一个canvas,它将创建一个场景图。斯温不是这么做的。

如果您在探查器中运行程序,您可以确切地看到时间花在了什么地方;如果您在调试器中运行程序,您可以看到canvas缓冲区变得有多大。

 类似资料:
  • 为了在JavaFX11中创建Jasper报表,我使用了动态报表。我正在Swing节点中加载报表,但Jasper报表只有在我单击stack窗格区域时才会出现,而所有其他组件只有在我悬停在所有这些组件上时才可见。组件和报表内容不是立即加载的,而不是在鼠标悬停时显示的,而报表是在滚动到堆栈窗格上时显示的。 因为这是Java8中的bug,并且似乎已经解决了,但是在Java11中,我也遇到了同样的问题。 更

  • 我知道这是一个简单的问题,但没有比堆栈溢出更好的问题了。我一直在开发一个Java桌面应用程序,它连接到远程数据库,并使用大量JTables和jasper报表。我已经到了必须开始考虑用户界面的时候,我注意到我可以使用JavaFX来实现用户界面。根据我一直在做的一些研究,JavaFX似乎提供了比Swing更好的用户界面。我的问题是,JavaFX适合我的应用程序吗?当我的应用程序使用大量数据库查询、表和

  • 问题内容: 我有一个非常大的程序,当前正在使用SWT。该程序可以在Windows,Mac和Linux上运行,它是一个包含许多元素的大型桌面应用程序。现在SWT有点老了,我想切换到Swing或JavaFX。我想听听您对三件事的想法。 我主要关心的是桌面GUI应用程序会更好吗?(我在网上看过,很多人认为JavaFX与Swing一样好,但是除了简单的见解大战之外,我没有看到很多有效的论点)。它必须在Wi

  • 我为即将到来的愚蠢问题提前道歉。 是否有JPanel用于javaFX的油漆组件方法的替代品?或者我应该只使用嵌入了Swing的JFXPanel? 例如,我认为时间轴与Swing中的计时器相同,面板/油漆组件对应的是什么? 编辑:例如,我们如何制作一个从x-y坐标到另一个坐标的圆的动画?(当然,不使用TranslateTransition) 我试着用canvas画画,但我不知道如何不断更新画布,比如

  • 我对线阵图有问题。 我不明白,为什么不渲染数据: Fxml文件:

  • 我正在尝试将自定义对象从JPanel拖放到JavaFX场景<为了实现这一点,我创建了一个带有自定义对象和自定义TransferHandler的简单应用程序。在本例中,我的问题是,当我在