慢速双缓冲方法

时间:2015-08-18 23:13:28

标签: java performance swing graphics java-2d

我一直试图在我的游戏库中实现双缓冲,但它比没有它时显着慢。

这是我实现它的类。基本上,它绘制到图像上,然后将图像绘制到JPanel的图形上(pg)。

public abstract class DrawingPanel extends GameLoop {

    private BufferedImage image;
    private Graphics2D ig;
    private Graphics pg;

    private int backgroundRGB;

    public DrawingPanel(final int fps, final int ups, final JPanel panel, final Color background) {
        super(fps, ups);
        initialize(panel, background);
    }

    /**
     * Creates a panel with 60 fps and 120 ups
     *
     * @param panel
     * @param background
     */
    public DrawingPanel(final JPanel panel, final Color background) {
        this(60, 120, panel, background);
    }

    public DrawingPanel(final JPanel panel) {
        this(panel, Color.WHITE);
    }

    public DrawingPanel(final int ups, final JPanel panel, final Color background) {
        super(ups);
        initialize(panel, background);
    }

    private void initialize(final JPanel panel, final Color background) {
        image = GraphicsUtils.createImage(panel.getWidth(), panel.getHeight(), Transparency.OPAQUE);
        ig = (Graphics2D) image.getGraphics();
        pg = panel.getGraphics();
        GraphicsUtils.prettyGraphics(ig);
        backgroundRGB = background.getRGB();

        panel.addMouseListener(this);
        panel.addMouseMotionListener(this);
        panel.addKeyListener(this);
        panel.addMouseWheelListener(this);

        panel.setFocusable(true);
        panel.requestFocusInWindow();
    }

    @Override
    public void draw() {
        // set background
        Arrays.fill(((DataBufferInt) image.getRaster().getDataBuffer()).getData(), backgroundRGB);

        // draw on the buffer
        draw(ig);
        // draw our buffer to the screen
        pg.drawImage(image, 0, 0, null);
    }

    public abstract void draw(Graphics2D g);

}

结果:measurement one 这意味着25% - 6%= 19%的时间仅用于绘制方法!

我认为可能是因为我使用Array.fill,但事实证明这不是一个无用的过早优化;"如果我用

替换该行
ig.setColor(backgroundColor);
ig.fillRect(0, 0, image.getWidth(), image.getHeight());

花费的时间甚至更长:26 - 5%= 21%。有什么方法可以加速这种方法吗?

顺便说一下,GraphicsUtils.createImage会从我的GraphicsConfiguration创建一个兼容的图片。

如果您想查看整个代码,整个库都是on github

1 个答案:

答案 0 :(得分:1)

这不是绘画在Swing中的作用 - > pg = panel.getGraphics();这是一个非常糟糕的主意。你正在Swing的被动渲染引擎和你试图绘制一个快照和#34;组件。

当您正确使用Swing组件时,内部双重缓冲,但是,您需要使用API​​。

首先查看Performing Custom PaintingPainting in AWT and Swing,了解有关绘画如何在Swing中工作的详细信息

基本上,正在发生的事情是,您使用getGraphics的结果绘制到面板,RepaintManager即将出现并决定是否需要更新您的组件并重新绘制它,生成一个空白面板,重复非常快。这就是造成你闪烁的原因。在Swing中,您不能控制绘制过程,您只能要求在绘制周期发生时通知(例如覆盖paintComponent)并向绘画系统请求重绘应该发生,但它&#39 ;直到油漆系统,实际决定何时发生油漆循环。

相反,首先要覆盖面板的paintComponent方法,然后在其中执行所有自定义绘制。使用repaint请求更新组件。

如果你真的"需要一个活跃的绘画过程,然后查看BufferStrategyBufferStrategy and BufferCapabilities,它为您提供了直接控制何时将输出推送到屏幕设备的方法。