3

Should I implement Image as back buffer myself or there are already made components or options to activate back buffer?

My goal is to persist drawings on window move and hide/show...

UPDATE

I have tried to use JPanel so that I think it should work if it has a buffer, but failed:

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);

Here circles are drawn on mouse clicks but disappear if window resize. So, no buffer apparently exist.

If component has buffer I would be able to draw something on it and it will persist on resize.

May be there is some way to access JPanel's buffer, other that getGraphics?

UPDATE 2

Below is how I did buffer manually. My question is isn't it done in the library already. Example resamples buffer on resize which is not mandatory.

    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;
    }
}
Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385

1 Answers1

2

All you need is a JPanel, which by default is automatically is double buffered (see here for more), you can than simply override paintComponent(..) and do all drawing there and than add the JPanel to a container like JFrame.

Have a look here for more:

You might also want to fully control the repainting cycle of your JPanel, this can be done by calling setIgnoreRepaint(true).

Alternatively you may want to look at BufferStrategy and BufferCapabilities (which will allow you some advanced functions but for all intensive purposes JPanel with overriden paintComponent and automatic double buffering and setIgnoreRepaint(true) is equivalent), this is usually implemented with a Canvas like so:

BufferStrategy myStrategy;

while (!done) {
    Graphics g = myStrategy.getDrawGraphics();
    render(g);//draw the frame/graphics
    g.dispose();
    myStrategy.show();
}
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • Sorry, what for should I override `paintComponent` if `JPanel` has buffer as you said? `paintComponent` is called each time component requires to redraw, so this is for case visual information is to be regenerated each time. – Suzan Cioc Dec 05 '12 at 14:53
  • @SuzanCioc the only way I know of doing that is by creating an array list which holds each oval you draw, in paintComponent you will than iterate through the array. And redraw ovals. – David Kroukamp Dec 05 '12 at 15:15
  • @SuzanCioc the only way I know of doing that is by creating an array list which holds each oval you draw, in paintComponent you will than iterate through the array. And redraw ovals. Here is a similar answer which will help, it however draws rectangles: http://stackoverflow.com/a/13359279/1133011 – David Kroukamp Dec 05 '12 at 15:21