1

I am having problem in creating an transparent rectangle over blurred background. I am trying to do this task on glasspane. Here is my code snippet.

void createBlur() {
    alpha = 1.0f;
    JRootPane root = SwingUtilities.getRootPane(jf);
    blurBuffer = GraphicsUtilities.createCompatibleImage(jf.getWidth(), jf.getHeight());
    Graphics2D g2d = blurBuffer.createGraphics();
    root.paint(g2d);
    g2d.dispose();

    backBuffer = blurBuffer;
    blurBuffer = GraphicsUtilities.createThumbnailFast(blurBuffer, jf.getWidth() / 2);
    blurBuffer = new GaussianBlurFilter(5).filter(blurBuffer, null);
}

where, backBuffer and blurBuffer are objects of BufferedImage & jf = JFrame, alpha is used for opacity. The above method create an Blurred Effect very well.

Here is the code which creates an transparent rectangle over Panel

protected void paintComponent(Graphics g) {
    int x = 34;
    int y = 34;
    int w = getWidth() - 68;
    int h = getHeight() - 68;
    int arc = 30;

    //Graphics2D g2 = currentGraphics.createGraphics();
    //g2.drawImage(currentGraphics, 0, 0, null);
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    g2.setColor(new Color(0, 0, 0, 220));
    g2.fillRoundRect(x, y, w, h, arc, arc);

    g2.setStroke(new BasicStroke(1f));
    g2.setColor(Color.WHITE);
    g2.drawRoundRect(x, y, w, h, arc, arc);

    g2.dispose();
}

Now where I stuck is how do I paint the blurred effect and transparent rectangle at the same time. I didn't posted whole code over here, if anyone wish to see the code here the link.

And here is an desired image of sample output. Thanks in advance.

enter image description here

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Vighanesh Gursale
  • 921
  • 5
  • 15
  • 31
  • For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete and Verifiable Example). And please clarify re the screen shot. Is that the desired effect or what you get now? If 'now', what is wrong with it? – Andrew Thompson Apr 22 '14 at 10:09
  • 1
    BTW about the link to your Google share drive. Few people will follow it, even fewer will 'request access'. At least do people the courtesy of marking the share file as 'public' to anyone with the link. – Andrew Thompson Apr 22 '14 at 10:11
  • @AndrewThompson this is the desired output and this output should come. I am able to create an transparent rectangle and blurred background but I don't have any idea how do I merge them together. And sorry for not sharing the file as 'Public' – Vighanesh Gursale Apr 22 '14 at 10:18
  • hmm ... how is this related to swingx? – kleopatra Apr 22 '14 at 11:24
  • @kleopatra SwingX lib provides some basic Classes to get the Blur effects using GaussianBlurFilter and it provides some extra attributes to create effective GUI like JXPanel offers a public property called alpha which can be used to change the translucency of the container and its children that's why I used SwingX – Vighanesh Gursale Apr 22 '14 at 11:33
  • if you are using JXPanel, you should ... at least mention that fact ;-) Plus use a painter instead of overriding paintComponent. – kleopatra Apr 22 '14 at 11:43
  • A call to super.paintComponent won't hurt to much. Wouldn't you just paint the blur image first and the rectangle ontop of it...? – MadProgrammer Apr 22 '14 at 12:11
  • @MadProgrammer that's what I'm trying to do,did you checked that in which I've written the whole code. – Vighanesh Gursale Apr 22 '14 at 12:29
  • @VighaneshGursale Yes and from what I can tell, that's not what you're doing... – MadProgrammer Apr 23 '14 at 00:19

1 Answers1

2

I'm trying to make heads and tails of your code...

You fail to call super.paintComponent...this could lead you into a same serious issues if you're not careful. General rule of thumb, just call it ;)

Be careful when modifiying the state of a Graphics context, for example...

g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

Will affect ALL components painted after this one and could cause some interesting graphical glitches you weren't expecting...

jf.getGlassPane().setVisible(false);
glassPanel = new GlassPanel();
jf.getGlassPane().setVisible(true);

Seems pointless, as the component set using jf.setGlassPane(glassPanel); will still be the component that is made visible when you call jf.getGlassPane().setVisible(true);. This also means that the GlassPane component is never used...

Checking isVisible in paintComponent is pointless, as Swing is clever enough to know not to paint invisible components...

Now, having said all that...

If you wanted to paint on top of the BlurPanel you would either...paint content after the blurBuffer is drawn, so you are drawing ontop of it OR add another component onto the BlurPanel pane which contains the drawing logic you want to apply...

This is a basic example of that concept. This adds another panel onto the glass pane which paints the custom frame of the panel as I want.

This example uses personal library code and is intended as an example of the concept alone, not a completely runnable example.

BeforeAfter

import core.ui.GlowEffectFactory;
import core.ui.GraphicsUtilities;
import core.util.ByteFormatter;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class TransparentTest {

    public static void main(String[] args) {
        new TransparentTest();
    }

    public TransparentTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage background;
        private BlurredGlassPane blurredGlassPane;

        private InfoPane infoPane;

        public TestPane() {
            try {
                background = ImageIO.read(new File("get your own image"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            blurredGlassPane = new BlurredGlassPane();
            blurredGlassPane.setLayout(new GridBagLayout());
            infoPane = new InfoPane();
            infoPane.setFile(new File("get your own image"));
            blurredGlassPane.add(infoPane);

            JButton click = new JButton("Click");
            click.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Window win = SwingUtilities.getWindowAncestor(TestPane.this);
                    if (win instanceof JFrame) {
                        JFrame frame = (JFrame) win;
                        frame.setGlassPane(blurredGlassPane);
                        blurredGlassPane.setVisible(true);
                    }
                }
            });

            setLayout(new GridBagLayout());
            add(click);
        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - background.getWidth()) / 2;
                int y = (getHeight() - background.getHeight()) / 2;
                g2d.drawImage(background, x, y, this);
                g2d.dispose();
            }
        }
    }

    public static class InfoPane extends JPanel {

        protected static final int RADIUS = 20;
        protected static final int FRAME = 4;
        protected static final int INSET = RADIUS + FRAME;
        protected static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance();

        private JLabel name;
        private JLabel path;
        private JLabel length;
        private JLabel lastModified;
        private JLabel canExecute;
        private JLabel canRead;
        private JLabel canWrite;
        private JLabel isDirectory;
        private JLabel isHidden;

        public InfoPane() {
            setBorder(new EmptyBorder(INSET, INSET, INSET, INSET));
            setOpaque(false);
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.WEST;
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            name = createLabel(Font.BOLD, 48);
            add(name, gbc);

            gbc.gridy++;
            path = createLabel();
            add(path, gbc);

            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 2;
            gbc.anchor = GridBagConstraints.WEST;

            length = createLabel();
            lastModified = createLabel();
            add(createLabel("Size: "), gbc);

            gbc.gridx++;
            gbc.insets = new Insets(0, 0, 0, 10);
            add(length, gbc);

            gbc.insets = new Insets(0, 0, 0, 0);
            gbc.gridx++;
            add(createLabel("Last Modified: "), gbc);

            gbc.gridx++;
            add(lastModified, gbc);
        }

        public JLabel createLabel(String text) {

            JLabel label = new JLabel(text);
            label.setForeground(Color.WHITE);
            return label;

        }

        public JLabel createLabel() {

            return createLabel("");

        }

        public JLabel createLabel(int style, float size) {

            JLabel label = createLabel();
            label.setFont(label.getFont().deriveFont(style, size));
            return label;
        }

        public void setFile(File file) {

            name.setText(file.getName());
            try {
                path.setText(file.getParentFile().getCanonicalPath());
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            length.setText(ByteFormatter.format(file.length()));
            lastModified.setText(DATE_FORMAT.format(new Date(file.lastModified())));
            file.canExecute();
            file.canRead();
            file.canWrite();
            file.isDirectory();
            file.isHidden();

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
            Graphics2D g2d = (Graphics2D) g.create();
            GraphicsUtilities.applyQualityRenderingHints(g2d);
            int width = getWidth() - 1;
            int height = getHeight() - 1;
            int buffer = FRAME / 2;
            RoundRectangle2D base = new RoundRectangle2D.Double(buffer, buffer, width - FRAME, height - FRAME, RADIUS, RADIUS);
            g2d.setColor(new Color(0, 0, 0, 128));
            g2d.fill(base);
            g2d.setColor(Color.WHITE);
            g2d.setStroke(new BasicStroke(FRAME, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2d.draw(base);
            g2d.dispose();
        }

    }

    public class BlurredGlassPane extends JPanel {

        private BufferedImage background;

        @Override
        public void setVisible(boolean visible) {
            if (visible) {
                Container parent = SwingUtilities.getAncestorOfClass(JRootPane.class, this);
                if (parent != null) {
                    JRootPane rootPane = (JRootPane) parent;

                    BufferedImage img = new BufferedImage(rootPane.getWidth(), rootPane.getHeight(), BufferedImage.TYPE_INT_ARGB);
                    Graphics2D g2d = img.createGraphics();
                    rootPane.printAll(g2d);
                    g2d.dispose();

                    background = GlowEffectFactory.generateBlur(img, 40);
                }
            }
            super.setVisible(visible);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(background, 0, 0, this);
        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks for giving me a demo, but I don't have so much knowledge of RenderingHints and many things in Graphics2D because java docs didn't provide so much informations about the RenderingHints and their Constants. It will take time for me to understand your answer but whatever I understand just tell me is it right or wrong? 1. create a Panel which holds background image or gradient 2. create blur effect of it and simaltaneously create the details panel (transparent rectangle ). 3. Draw the transparent rectangle over that panel 4. Finally draw the Image over the rootpane. – Vighanesh Gursale Apr 23 '14 at 06:22
  • `jf.getGlassPane().setVisible(false); glassPanel = new GlassPanel(); jf.getGlassPane().setVisible(true);` in these statements I was trying to change the content of glasspane and as the rule of swings says don't try to change the content of any visible component. That's why I was trying to do those things. – Vighanesh Gursale Apr 23 '14 at 06:27
  • Not really. 1. Create background panel (image/gradient). 2. Create blur image of this. 3. Create panel that can paint the blur image. 4. Add what ever to the "blur panel". The blur panel MUST appear above the background panel and everything must appear above that... – MadProgrammer Apr 23 '14 at 06:28
  • It might be silly answer but what `jf.setGlassPane(glassPanel)` does whether it sets the `glassPanel` as `glassPane` or just add the `glassPanel` over the rootpane?? – Vighanesh Gursale Apr 23 '14 at 06:40
  • `jf.setGlassPane(glassPanel);` sets the component that would be used as the root panes "glass pane" and is returned by `jf.getGlassPane()`. `glassPanel = new GlassPanel();` only changes the reference that `glassPanel` and not what `JFrame` is using... – MadProgrammer Apr 23 '14 at 06:43
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/51316/discussion-between-vighanesh-gursale-and-madprogrammer) – Vighanesh Gursale Apr 24 '14 at 05:06