Tak, když už jsem to nakousl nadhodím ti menší sample:

Uděláš si víc Image, do kterých si kreslíš to co chceš. 1 Image = 1 vrstva. Kvůli blikání je lepší ještě zařídit doublebuffer, ale ten snad i JFrame má. Teď se nebudu hádat. Nechce se mi prolézat zdrojáky Javy

No nakonec stačí překreslit tvoje vrstvy přes sebe (kresli odspoda nahoru samozřejmě, jako v reálu).

Když horní vrstvy úplně nevyplníš, tak to funguje nejspíš jak si přeješ.



Kód:
package javalayers;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;

/**
 *
 * @author Mike
 */
public class Main extends JFrame {

    BufferedImage   background;
    BufferedImage   drawLayer;
    BufferedImage   doubleBuffer;

    public Main() {
        
        this.background = new BufferedImage(400,400,BufferedImage.TYPE_INT_ARGB);
        this.drawLayer = new BufferedImage(400,400,BufferedImage.TYPE_INT_ARGB); 
        this.doubleBuffer = new BufferedImage(400,400,BufferedImage.TYPE_INT_ARGB); 
        
        Graphics2D  g2 = (Graphics2D) drawLayer.getGraphics();
        g2.drawString("Hello world, I am drawing layer", 100,100);
        
        g2 = (Graphics2D) background.getGraphics();
        g2.setColor(new Color(200,200,200));        //nastavim kreslici barvu
        g2.fillRect(0, 0,400, 400);                 //vyplnim pozadi nejakou barvou
      
    }
    
    @Override
    public void paint(Graphics g) {
        super.paint(g);
       
        doubleBuffer.flush(); 
        Graphics2D  g2 = (Graphics2D) doubleBuffer.getGraphics();
        
        g2.drawImage(background, null, 0, 0);
        g2.drawImage(drawLayer, null, 0, 0);
        g.drawImage(doubleBuffer, 0, 0, null);
    }

    
   
    public static void main(String[] args) {
       
            Main m = new Main();
            m.setSize(new Dimension(400,400));
            m.setVisible(true);
            m.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
           
    }


}