Multiple independent layers in Graphics

2019-09-09 23:31发布

Is it possible to have multiple independent drawing layers using Graphics? I actually need two layers (like in Photoshop, Gimp, Paint.NET, ...) on which I can draw objects and I want all objects of the top layer appear above all objects of the bottom layer, independent of the order in which objects are drawn. It is not the case that I can first draw all objects of one layer and then draw all objects of the other.

Example:

  1. draw red filled circle on bottom layer
  2. draw green rectangle on top layer
  3. draw red filled rectangle on bottom layer
  4. draw green circle on top layer

Desired result: the two empty green objects should be rendered above the two filled red objects.

I fiddled around using JLayeredPane and Canvas and the closest I could get was a Canvas on top of a JComponent but unfortunately the Canvas background cannot be transparent, so everything that is drawn in the JComponent is covered by the Canvas background.

Can you tell me how to achieve this (if it's possible after all)?

1条回答
该账号已被封号
2楼-- · 2019-09-09 23:48

There are a few ways to do it. You can keep a list of BufferedImages as your layers of images and render them accordingly:

class AdvancePaint extends JPanel(){
    ArrayList<BufferedImage> layers;
    //Other constructors, variables, initializations not shown

    class AdvancePaint(){
        layers = new ArrayList<BufferedImage>();
    }

    public void addLayer(BufferedImage layer){
        layers.add(layer);
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        for(BufferredImage buf : layers)  //render all layers
            g.drawImage(buf, 0, 0, width, height, null);
    }
}

The above codes will render the BufferedImage from the list in accordance to the order they are added to the list. If you do not want to paint all layers on every repaint, you can always add another draw(Graphics g) method which you can pick the layers to be drawn onto another BufferedImage. Then only draw this BufferedImage on paintComponent(g).

Since the layers are stored as a Collection, you can always change their rendering order by sorting them or changing their position in the list.

You can always tweak on the minor details from my example to customize what you need.


To add a Layer:

BufferedImage layer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
advancePaint.addLayer(layer);

Using BufferedImage.TYPE_INT_ARGB, the background will be transparent, hence other layers will be able to "shine through".

查看更多
登录 后发表回答