Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Swing

Arbitrary Shaped Transparent JFrame in Java Swing

4.67/5 (3 votes)
11 Oct 2010Apache5 min read 61.5K   4.4K  
Create a Shape for a custom JFrame and apply a transparency effect (0 to 1 alpha value) on entire window, on Windows Platform

Introduction

The aim of this work is to create this cool window:

screen1.PNG

We have a copy of JFrame behind, but with cool transparency effect and a rounded shape form. The difficulty is to recreate the window header, with title and button for window_state. But this article can clarify any doubts.

Graphic Package

The UML representation of simple package for our purpose is:

uml.PNG

RoundedWindow is the object shown in previews screenshot. The basic component of package is ShapedFrame, this is an inheritance of JFrame with the ability to modify its shape (from simple rect shape of every window, even to a circle form) and can apply a transparency effect , on platforms where it is possible.

The JAVA utility to do that is AWTUtilities, but this is not an official release so I create a Wrapper for this AWTUtilities with a maximum level of abstraction so that if AWTUtilities will be changed to another package, you have only to modify AWTUtilitiesWrapper references and not all occurrences in the source code.

Since ShapedFrame is the basic inheritance, we have to create an extension like "SHAPEX"Frame, where in our case is RoundedRectFrame. This object extends ShapedFrame able to set a transparency and a shape form, and just have an alpha value and a basic shape form management. See below.

Finally there is an utility object: VisualDragHandle. What is that??? First, I say that a custom shape JFrame has to be "indecorated", so it does not have a handle for dragging all around the screen. So this is an object that has the ability to drag parent window when we click with mouse on itself. The only "must" is that we have to add it directly to contentPane of JFrame.

Now follows a simple explanation of each class.

ShapedFrame

Java
public abstract class ShapedFrame extends JFrame {

 protected Shape shape;
 protected float alpha = 1f;
 public ShapedFrame() {
        //If is DECORATED effects are disabled
        setUndecorated(true);
        setVisible(true);
        setListenersForEffects();
    }

 //.........................

 private void setListenersForEffects() {
        //It is important to upadate visual effect on form resize.
        addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent evt) {
                updateFrameEffects();
            }
        });
    }
 
 //.........................
 
 public void updateFrameEffects() {
        updateShape();
        try {
            AWTUtilitiesWrapper.setWindowShape(this, shape);
            if (shape != null) {
                AWTUtilitiesWrapper.setWindowOpacity(this, alpha);
            }
        } catch (Exception ex) {
            Logger.getLogger(ShapedFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
  
 //.........................
} 

This is not the entire class but only the most important methods. There is the base constructor for setting "UNDECORATE" state of JFrame and for adding Listeners. updateFrameEffects is the core of advanced graphic of this package: it invokes two important methods of AWTUtilities for transparency and shaping. This method has to be called everytime when JFrame will be resized. setListenersForEffects links previous method to resize event.

The only properties are just alpha and shape.

RoundedRectFrame

Whereas the previous class is abstract (because every shape type has a different behaviour), we have to implement a real shape class like RoundedRectFrame.

Java
public class RoundedRectFrame extends ShapedFrame {

    protected Dimension arcSize = new Dimension(50, 50);

    public RoundedRectFrame() {
        super(300, 200);
        setShapeToDefault();
    }

    public final void setShapeToDefault() {
        shape = new RoundRectangle2D.Double
	(0d, 0d, getWidth(), getHeight(), arcSize.width, arcSize.height);
    }

    @Override
    public void updateShape() {
        setShapeToDefault();
    }
}

Omitting getters and setters, this is the entire class. It is very simple because it has only to explain to father abstract class the behaviour of a RoundedRect shape when we want to draw it, resize it, and so on... and then? It only resizes the base RoundedRect by width and height of source JFrame. The peculiarity is to declare updateShape abstract in parent class; this method will be invoked every time JFrame updates itself; so overriding this method we will be sure that displayed shape is what we want.

RoundedWindow

This class is the end of workflow. The class is more comlex so I can't display all the source code.

Java
public class RoundedWindow extends RoundedRectFrame {

    private JLabel titleLabel;
    private JPanel container;

    public RoundedWindow(JPanel defaultPanel) {
        super();
        super.setLayout(new BorderLayout());
        container = defaultPanel;
        addHeader();
        setTitle("Rounded Window");
    }

    private void addHeader() {
        titleLabel = new JLabel(getTitle());
        titleLabel.setForeground(Color.white);

        VisualDragHandle dragHandle = new VisualDragHandle(this);


        dragHandle.add(titleLabel);
        dragHandle.add(getIconifyComponent());
        dragHandle.add(getCloseComponent());

        super.add(dragHandle, BorderLayout.NORTH);
        super.add(container, BorderLayout.CENTER);
    }

	//............................
}

This is only the base of the class. The default constructor gets as parameter a JPanel because it creates a custom JFrame where contentPane is not the effective pane where we work on. As you can see in the first screenshot, the RoundedWindow is made of a DarkGray header with title, and a JPanel with image as container. That is a JPanel I mean. Infact the rest of class is an override of JFrame methods for component management. An example is:

Java
@Override
    public Component add(Component comp) {
        if (container != null) {
            return container.add(comp);
        }
        return super.add(comp);
    }

Why? Some users have been understood: after we have added a custom JPanel as container, when we will add a component to JFrame we want that component will be added to JPanel instead. Write comments if you don't understand.

addHeader method is the creation of header. Basically, we create a VisualDragHandle as seen before, and we add to this Handle, that is a simple JPanel, several elements like title and two object for Iconify and Close. The objects are retrieved by two methods: getIconifyComponent and getCloseComponent, simple methods that create two custom components, in this case two simple JLable with relative events, and return them to addHeader method for adding into header.

Others

In the main class of source code, there is that core code:

Java
CustomPanel panel = new CustomPanel();
CustomPanel panel2 = new CustomPanel();
panel.setImage("glass.jpg");
panel2.setImage("glass.jpg");

//Standard JFrame creation
JFrame old = new JFrame();
old.setSize(700, 500);
old.setLayout(new BorderLayout());
old.add(panel2, BorderLayout.CENTER);
old.setVisible(true);

//New Cool Frame cration
final RoundedWindow roundedFrame = new RoundedWindow(panel);
roundedFrame.setSize(700, 500);
roundedFrame.setAlpha(0.9f);
roundedFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
roundedFrame.center();

CustomPanel is a simple panel (with Dr.House photo & data: ), I have created this with netbeans so you ignore code. The peculiarity is the inheritance from ImagePanel that is a simple JPanel with image background, see article on DraggableImageComponent that is nearly the same thing. The inheritance is made because I want a cool glass background for my window.

The main code then creates with this custom component two frames: a simple JFrame and a RoundedWindow frame. You can see the visual differences among two JFrames in the first screenshot.

Conclusions

You now have a reusable component like RoundedWindow to create your simple small windows with transparency effects and rounded shape. Although you can extend ShapedFrame for your custom shapes like : Ovals, Circles, or Polyline; simply follow the RoundedRectFrame way. If you want (..with a simple vote!!! : ) I can post my work about several Shapes for JFrames for create Widget like translucent Clock or Calendar and so on...

Prerequisites

Now I have tested this work on:

  • Windows Vista
  • Windows 7

The build release of JRE is jre1.6.0_17 and currently dosen't work on Linux gnome desktop. I haven't tried it on KDE. So write to me if you try.

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0