2

Following Oracle's Myopia guide, I have a simple JPanel which is added to a JFrame as a JLayer. Simple enough, this blurs the JPanel's components. However, I'm trying to add a second JPanel above this JPanel (meaning that it won't get blurred).

Simple JPanel along with Main-method:

public class ContentPanel extends JPanel {

    public ContentPanel() {
        setLayout(new BorderLayout());
        add(new JLabel("Hello world, this is blurry!"), BorderLayout.NORTH);
        add(new JLabel("Hello world, this is blurry!"), BorderLayout.CENTER);
        add(new JButton("Blurry button"), BorderLayout.SOUTH);
    }

    public static void main(String[] args) {

        JFrame f = new JFrame("Foo");
        f.setSize(300, 200);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationRelativeTo(null);

        LayerUI<JComponent> layerUI = new BlurLayerUI();
        JPanel panel = new ContentPanel();
        JLayer<JComponent> jlayer = new JLayer<JComponent>(panel, layerUI);

        f.add(jlayer);
        f.setVisible(true);
    }

}

BlurLayerUI which blurs its "children":

class BlurLayerUI extends LayerUI<JComponent> {
    private BufferedImage mOffscreenImage;
    private BufferedImageOp mOperation;

    public BlurLayerUI() {
        float ninth = 1.0f / 9.0f;
        float[] blurKernel = { ninth, ninth, ninth, ninth, ninth, ninth, ninth,
                ninth, ninth };
        mOperation = new ConvolveOp(new Kernel(3, 3, blurKernel),
                ConvolveOp.EDGE_NO_OP, null);

    }

    @Override
    public void paint(Graphics g, JComponent c) {
        int w = c.getWidth();
        int h = c.getHeight();

        if (w == 0 || h == 0) {
            return;
        }

        // Only create the offscreen image if the one we have
        // is the wrong size.
        if (mOffscreenImage == null || mOffscreenImage.getWidth() != w
                || mOffscreenImage.getHeight() != h) {
            mOffscreenImage = new BufferedImage(w, h,
                    BufferedImage.TYPE_INT_RGB);
        }

        Graphics2D ig2 = mOffscreenImage.createGraphics();
        ig2.setClip(g.getClip());
        super.paint(ig2, c);
        ig2.dispose();

        Graphics2D g2 = (Graphics2D) g;
        g2.drawImage(mOffscreenImage, mOperation, 0, 0);
    }
}

This will produce the following:

enter image description here

I've tried to simply add the second JPanel to the JFrame after the first, this only results in that the second panel takes up all the space. Using various layout-managers and set-Maximum/Preferred-size() methods won't do any good. Nor will making the second panels background transparent.

How can I add add a JPanel with fixed size above a JLayer, thus allowing part of the first panel to appear (still blurry)?

Zar
  • 6,786
  • 8
  • 54
  • 76
  • why not just change the size of the blur to contain only the components you want? – David Kroukamp Dec 03 '12 at 16:22
  • @DavidKroukamp The panel which will appear over all other content is containing a loading image and some other elements, and will be faded in / out when needed. Every other panels will therefore be blurred as a part of this, hence the JLayer. – Zar Dec 03 '12 at 16:32
  • @Zar, Does the regular content really need to be blurred? I'm somewhat confused as to why users need to see a blurry application behind your loading image. – Eric Hydrick Dec 04 '12 at 14:54

1 Answers1

1

Going by your comment that you want to blur data while you have a loading image, I would recommend a dialog. You can put your unblurred panel on the dialog, turn off it's frame and title bar with setUndecorated(true), and set it's default close behavior to DO_NOTHING_ON_CLOSE to prevent the user from closing the dialog before the application is loaded. This would sit on top of your blurred panels, but since it's not part of the BlurLayerUI, it wouldn't be blurred.

Eric Hydrick
  • 3,467
  • 2
  • 28
  • 41