自定义摇摆组件的图像缓冲区?

时间:2012-12-05 11:41:37

标签: java image swing buffer

我应该自己实现Image作为后台缓冲区还是已经有用于激活后台缓冲区的组件或选项?

我的目标是在窗口移动和隐藏/显示上持续绘图......

更新

我曾尝试使用JPanel,以便我认为它应该有效,如果它有一个缓冲区,但失败了:

final JPanel panel = new JPanel();

            panel.addMouseListener(new MouseListener() {

                @Override
                public void mouseReleased(MouseEvent e) {
                }

                @Override
                public void mousePressed(MouseEvent e) {
                }

                @Override
                public void mouseExited(MouseEvent e) {
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                }

                @Override
                public void mouseClicked(MouseEvent e) {
                    Graphics2D g2d = (Graphics2D) panel.getGraphics();
                    g2d.drawOval(e.getX()-50, e.getY()-50, 100, 100);
                }
            });

            JFrame frame = new JFrame("JPanel Buffer Test");
            frame.add(panel, BorderLayout.CENTER);
            frame.pack();
            frame.setBounds(100,100, 800, 600);
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.setVisible(true);

此处圆圈是通过鼠标点击绘制的,但如果窗口调整大小则会消失。所以,显然没有缓冲区。

如果组件有缓冲区,我可以在其上绘制一些东西,它会在调整大小时持续存在。

可能有某种方法可以访问JPanel的缓冲区,getGraphics的其他缓冲区?

更新2

下面是我手动缓冲的方法。我的问题是它已经在图书馆中完成了。 示例重新调整resize上的缓冲区,这不是必需的。

    private BufferedImage bufferedImage = null;

@Override
protected void paintComponent(Graphics g) {
    if( bufferedImage != null ) {
        g.drawImage(bufferedImage, 0, 0, null);
    }
}

@Override
public void setBounds(int x, int y, int width, int height) {

    if( bufferedImage == null ) {
        bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    }
    else {
        if( bufferedImage.getWidth() != width || bufferedImage.getHeight() != height ) {
            BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

            AffineTransform at = new AffineTransform();
            at.scale((double)width/bufferedImage.getWidth(), (double)height/bufferedImage.getHeight());

            AffineTransformOp scaleOp = 
                   new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);

            bufferedImage = scaleOp.filter(bufferedImage, scaledImage);
        }
    }
    super.setBounds(x, y, width, height);
}


public Graphics2D createImageGraphics() {
    if( bufferedImage != null ) {
        return bufferedImage.createGraphics();
    }
    else {
        return null;
    }
}

1 个答案:

答案 0 :(得分:2)

您需要的只是JPanel,默认情况下会自动双重缓冲(有关详情,请参阅here),您可以简单地覆盖paintComponent(..)并完成所有绘图,然后将JPanel添加到JFrame等容器中。

请点击此处了解更多信息:

您可能还想完全控制JPanel的重新绘制周期,可以通过调用setIgnoreRepaint(true)来完成。

或者,您可能需要查看BufferStrategy and BufferCapabilities(这将允许您使用一些高级功能,但用于所有密集目的JPanel并覆盖paintComponent和自动双缓冲setIgnoreRepaint(true)是等价的),这通常用Canvas实现,如下所示:

BufferStrategy myStrategy;

while (!done) {
    Graphics g = myStrategy.getDrawGraphics();
    render(g);//draw the frame/graphics
    g.dispose();
    myStrategy.show();
}