Java 7 : Translucency and shaped windows

Java 7 introduces very interesting features for desktop windows :

  • Transclucency for windows : Make a full window translucent with a specified alpha level
  • Per pixel translucency : Make a part of the window translucent.
  • Shaped windows : You can now create windows with a certain shape, like circle, ovale, triangle, ...

We'll see all this features in that post. All the examples are tested in Windows Seven 64 bits, because the transclucency isn't supported in Ubuntu 10.04 at the time I write the article.

First of all, you can now set the opacity of the window with the setOpacity(float opacity) of the Window class. With that, the entire window is made translucent. There is some limitations with that new method. An opacity less than 1.0 isn't supported if the window use full-screen mode or if the simple translucency isn't supported. You can test if the window transclucency is supported with the isWindowTranslucencySupported() method added to the GraphicsDevice class :

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
if (ge.getDefaultScreenDevice().isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.TRANSLUCENT)) {
    System.out.println("Window translucency isn't supported on your system. ");
}

We know enough to write a first translucent window :

package com.wicht.java7.swing;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;

public class TranslucentWindow extends JFrame {
    public TranslucentWindow() {
        super("Simple Translucency Demo");

        setSize(300, 200);

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        getRootPane().setDoubleBuffered(false);
        setOpacity(0.5f);

        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

                if (ge.getDefaultScreenDevice().isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.TRANSLUCENT)) {
                    new TranslucentWindow();
                }
            }
        });
    }
}

Note : We disable double buffering to remove artifacts that come when double buffer a translucent window.

That produce this result on my computer :

Java 7 Translucent Window

So, it's really simple to make a window translucent. But there is more you can do. You can also make only a set of pixel translucent using their background color. Like the translucent window, there is some limitations, the window must not be in full-screen and the system must support the per pixel translucency. You can test it the same way as the first time :

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

if (ge.getDefaultScreenDevice().isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) {
    System.out.println("Window translucency isn't supported on your system. ");
}

A simple making a grid of 16 panels more and more translucent :

package com.wicht.java7.swing;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class GriddedTranslucentWindow extends JFrame {
    public GriddedTranslucentWindow() {
        super("Java 7 Per Pixel Translucency");

        setSize(300, 320);

        getContentPane().setLayout(new GridLayout(4, 4));

        for(int i = 0; i < 16; i++){
            add(new AlphaPanel(255 - i * 12));
        }

        setBackground(new Color(0, 0, 0, 0));

        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

                if (ge.getDefaultScreenDevice().isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) {
                    new GriddedTranslucentWindow();
                }
            }
        });
    }

    private class AlphaPanel extends JPanel {
        private AlphaPanel(int alpha) {
            super();

            setBackground(new Color(0, 0, 255, alpha));
        }
    }
}

That give me this kind of result :

Java 7 : Per Pixel Translucency

The example is very simple of course, but you can imagine doing a lot of things using that feature.

And now a crazy new feature : shaped windows !

Java 7 allows you to create Window of whatever shape you want. You can create circle, triangle, elliptic windows or more complex shape, a smiley by example. To do that, you have now access to the setShape(Shape shape) method in the Window class. Like the other two, full screen mode is not allowed and the per pixel transparency must be supported by your computer :

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

if (ge.getDefaultScreenDevice().isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT )) {
    System.out.println("Window translucency isn't supported on your system. ")
}

Here is a little example combining a triangle and a circle :

package com.wicht.java7.swing;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;

public class ShapedWindow extends JFrame {
    public ShapedWindow() {
        super("Shaped Window");

        setUndecorated(true);

        setSize(new Dimension(200, 300));

        Polygon polygon = new Polygon();
        polygon.addPoint(0, 200);
        polygon.addPoint(100, 0);
        polygon.addPoint(200, 200);

        Ellipse2D.Double theCircle = new Ellipse2D.Double(0, 100, 1.0*200, 1.0*200);

        GeneralPath path = new GeneralPath();
        path.append(polygon, true);
        path.append(theCircle, true);

        setShape(path);

        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));

        add(Box.createHorizontalGlue());
        JLabel label = new JLabel("Shaped window");
        label.setForeground(Color.white);
        add(label);
        add(Box.createHorizontalGlue());

        getContentPane().setBackground(Color.blue);

        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

                if (ge.getDefaultScreenDevice().isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT)) {
                    new TranslucentShapedWindow();
                }
            }
        });
    }
}

This produce that sort of window :

Java 7 : Shaped Windows

And of course you can combine translucency and shaped windows adding setOpacity(0.5f) to your frame. For that the Per Pixel Translucency and the Per Pixel Transparency must be supported. That give us this kind of window :

Java 7 : Translucent Shaped Window

Here we are. We've now covered the new translucency features of Java 7. I think it's really interesting and make Java Desktop Applications more competitive. But I think there is still work to do in Swing before doing that kind of fun stuff.

Related articles

  • Ubuntu Lucid Lynx Tip : Put the window buttons to the right
  • Why and how I completely left Windows for Linux
  • Simplify Deep Learning Library usage on Linux and Windows!
  • Java 7 has been released!
  • Manage focus with Swing in Java
  • Java 7 : More dynamics
  • Comments

    Comments powered by Disqus