3

I was wondering if it were possible to layer ImageIcons in Java. I will be working with GIF images, and will have a grid of ImageIcons representing the "background" of my JPane.

When a certain condition is true, I need to be able to add an image that has transparency on top of the other image.

Regards, Jack Hunt

Jack H
  • 2,440
  • 4
  • 40
  • 63
  • as you see from the answers: many ways to Rome :-) Which to choose, depends on the exact requirements in your context. – kleopatra Feb 10 '12 at 12:39

4 Answers4

5

You could simply use g.drawImage(...) to draw them onto the panel in an overriden paintComponent method. That would be the easiest way to do that.

Because your question mentions ImageIcon, it would be correct to use it if your gif's are animated. Otherwise, BufferedImage is generally preferred. If you decide to keep to ImageIcon, you should use paintIcon(Component c, Graphics g, int x, int y) instead of g.drawImage(...).

If you want to add images dynamically, consider storing them in an array or ArrayList, then simply iterate through the array / list in your paintComponent.

For example:

JPanel panel = new JPanel(){
    @Override
    public void paintComponent(Graphics g){
       super.paintComponent(g);
       if(yourCondition){
           g.drawImage(img, x, y, this); // for example.
       }
    }
};

The other alternative is to create a private class which extends JPanel. For example:

public class OuterClass{
    // fields, constructors, methods etc..

    private class MyPanel extends JPanel{   
       // fields, constructors, methods etc..

       @Override
       public void paintComponent(Graphics g){
          super.paintComponent(g);
          if(yourCondition){
             g.drawImage(img, x, y, this); // for example.
          }
       }

    }
}

Side note: Any particular reason why you need to use GIF? PNG is generally better.

EDIT: (according to Andrew Thompson's idea)

In order to take a snapshot of all the images contained in the background...
A variant of the following idea:

BufferedImage background;

public void captureBackground(){
    BufferedImage img = GraphicsConfiguration.createCompatibleImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = img.createGraphics();
    for(ImageIcon i : imageIconArray){ // could be for(BufferedImage i : imageArray){
         i.paintIcon(this, g, 0, 0);   // g.drawImage(i, 0, 0, null);
    }
    g.dispose();
    background = img;
    // either paint 'background' or add it to your background panel here.
}
rtheunissen
  • 7,347
  • 5
  • 34
  • 65
5

yes that's possible and there are two correct ways

1) if is there only one Image then put JLabel with Icon to the GlassPane

2) use LayeredPane for <= Java6 (not Java7 user there is JLayer)

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • 3
    +1, but what is *incorrect* about a) the answers of paranoid-android & trashgod. b) rendering the entire lot to a single `BufferedImage` that is added to a label and updated when needed? It seems there are a lot of ways to skin this cat. ;) – Andrew Thompson Feb 10 '12 at 11:58
  • @Andrew Thompson even all that you deleted your answer interesting idea, pleeeeeeeeeeeeeeaaaaaaaaaaase example for that – mKorbel Feb 10 '12 at 11:58
  • I decided to delete it when I saw PA's better description of the same idea. As to example code, I avoided it since there are so many 'near variants' of this across SO ( and I really should be doing other things ;). – Andrew Thompson Feb 10 '12 at 12:00
  • Or did you mean an example of 'b'? – Andrew Thompson Feb 10 '12 at 12:01
  • @AndrewThompson that's a really good idea. Effectively taking a snapshot whenever the background is updated. I think it depends on how often (or how) the background will be changing. If it changes rapidly, there wouldn't be much point. Hardly, then yes it would be ideal. :) +1. – rtheunissen Feb 10 '12 at 12:02
  • @Andrew Thompson I have strong bases (your code) http://stackoverflow.com/a/7944388/714968, and untill now I never saw whatever, sure this code missed overlaying, there is only about to replace for Icon/ImageIcon on some period – mKorbel Feb 10 '12 at 12:02
  • +1 for `JLayeredPane`, but I've not tried it with `AlphaComposite`. – trashgod Feb 10 '12 at 12:09
  • @trashgod I've always found `JLayeredPane` to be a nightmare. For some reason I prefer painting to adding. No idea why. And `AlphaComposite` seems unnecessary seeing as the gif is translucent and the `JLabel`'s opacity would be false by default. What would `AlphaComposite` be used for? – rtheunissen Feb 10 '12 at 12:11
  • @paranoid-android AlphaComposite is same as impression of the suggesstion by (@AndrewThompson) – mKorbel Feb 10 '12 at 12:19
  • @all seems like as (@paranoid-android) maybe you ignored one of the answers to your very similair question by (@kleopatra) http://stackoverflow.com/a/8787294/714968, on bottom is sticked link to code_soouce for JLayer in Java6 – mKorbel Feb 10 '12 at 12:32
  • @mKorbel I did read that answer some time ago, though I'm not familiar with `jdk7 / JXLayer` etc. so even though it was a very good answer, my entire application is in `jdk6 Swing` so I will stick to it for now. Next project -> Java 7. – rtheunissen Feb 10 '12 at 12:36
  • BTW: glassPane is a per-rootpane notion, not per-panel - so most probably rather useless here (apart from its hard-to-handle characteristics ..) – kleopatra Feb 10 '12 at 12:37
  • @kleopatra could be confortable in case that Image / Icon / ImageIcon is dragged from somewhere for overlaying effects (animations / sliding / bluring) – mKorbel Feb 10 '12 at 12:50
  • @paranoid-android: Opacity and transparency are not the same, as discussed [here](http://stackoverflow.com/a/3518047/230513). The default mode, clarified [here](http://stackoverflow.com/a/9227314/230513), may be sufficient. – trashgod Feb 10 '12 at 16:18
  • @trashgod I'm very well aware of that. My suggestion was the use `JLabel` or `JComponent` which is already for all intents and purposes 'transparent', but because gif's don't support translucency, I suggested to use png instead, which should take care of any 'transparency' issues. – rtheunissen Feb 11 '12 at 00:20
  • @paranoid-android: Ah, I confounded GIF's _transparency_ with composite _translucency_. – trashgod Feb 11 '12 at 01:17
4

You can use the modes of AlphaComposite to achieve a variety of effects. There's an example and utility here.

Addendum: Note that the default composite mode for a platform's concrete implementation of Graphics2D is AlphaComposite.SRC_OVER, which may or may not be what you want.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
4

You could use the Overlay Layout to stack JLabels on top of one another.

Or you could use the Compound Icon to stack icons on top of one another.

camickr
  • 321,443
  • 19
  • 166
  • 288