10

I am trying to create a circle-shaped window that follows the mouse and pass clicks to the underlying windows.

I was doing this with Python and Qt (see Python overlay window) but then I switched to Java and Swing. However I'm not able to make the window transparent. I tried this method but it doesn't work, however I think that my system supports the transparency because if I start Screencast-O-Matic (which is in Java), the rectangle is actually transparent.

How can I achieve something like that? (I'm on Linux KDE4)

Community
  • 1
  • 1
Lord Spectre
  • 761
  • 1
  • 6
  • 21
  • 1
    Have you got any solution for this issue ? I am facing same issue.. I have made application like Screencast-O-Matic that works for Windows OS nicely but not working for the Linux..Please suggest here if you found anything , http://stackoverflow.com/questions/25009276/swing-works-different-on-different-platform – tarkikshah Jul 30 '14 at 09:28
  • 1
    No, I switched back to PyQt for my screencast application, because I had other issues with Java. – Lord Spectre Jul 30 '14 at 10:29

5 Answers5

11

Why did the Java tutorial How to Create Translucent and Shaped Windows fail to work? Are you using the latest version of Java 6 or Java 7? In the May/June issue of Java Magazine, there was a tutorial on shaped and transparent windows requiring java 7. You will probably need to sign up for Java magazine in order to read it. See if you can get this to run on your system:

import java.awt.*; //Graphics2D, LinearGradientPaint, Point, Window, Window.Type;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 * From JavaMagazine May/June 2012
 * @author josh
 */
public class ShapedAboutWindowDemo {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        //switch to the right thread
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("About box");
                //turn of window decorations
                frame.setUndecorated(true);
                //turn off the background
                frame.setBackground(new Color(0,0,0,0));
                frame.setContentPane(new AboutComponent());
                frame.pack();
                //size the window
                frame.setSize(500, 200);
                frame.setVisible(true);
                //center on screen
                frame.setLocationRelativeTo(null);
            }
        }
        );
    }

    private static class AboutComponent extends JComponent {
        public void paintComponent(Graphics graphics) {
            Graphics2D g = (Graphics2D) graphics;

            //create a translucent gradient
            Color[] colors = new Color[]{
                           new Color(0,0,0,0)
                            ,new Color(0.3f,0.3f,0.3f,1f)
                            ,new Color(0.3f,0.3f,0.3f,1f)
                            ,new Color(0,0,0,0)};
            float[] stops = new float[]{0,0.2f,0.8f,1f};
            LinearGradientPaint paint = new LinearGradientPaint(
                                        new Point(0,0), new Point(500,0),
                                        stops,colors);
            //fill a rect then paint with text
            g.setPaint(paint);
            g.fillRect(0, 0, 500, 200);
            g.setPaint(Color.WHITE);
            g.drawString("My Killer App", 200, 100);
        }
    }
}
Thorn
  • 4,015
  • 4
  • 23
  • 42
  • I'm on Java 6, that's why I used the compatibility methods on the bottom of the page... With your example I get [this](https://dl.dropbox.com/u/9287758/Immagini/JavaNoTransparency.png) – Lord Spectre Aug 07 '12 at 12:07
  • OK. The Java tutorial you site requires Java 6 update 10, so as long as you have that, it should work. If not, then there must be a linux compatibility issue and in that case I recommend you upgrade to JDK 7 and see if that fixes it. – Thorn Aug 07 '12 at 15:41
4

If you're using Java 6, you need to make use of the private API AWTUtilities. Check out the Java SE 6 Update 10 API for more details

EXAMPLE

This is a bit of quick hack, but it gets the idea across

public class TransparentWindow {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                MyFrame frame = new MyFrame();
                frame.setUndecorated(true);

                String version = System.getProperty("java.version");
                if (version.startsWith("1.7")) {


                    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                    GraphicsDevice graphicsDevice = ge.getDefaultScreenDevice();

                    System.out.println("Transparent from under Java 7");
                    /* This won't run under Java 6, uncomment if you are using Java 7
                    System.out.println("isPerPixelAlphaTranslucent = " + graphicsDevice.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT));
                    System.out.println("isPerPixelAlphaTransparent = " + graphicsDevice.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT));
                    System.out.println("isPerPixelAlphaTranslucent = " + graphicsDevice.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.TRANSLUCENT));
                    */
                    frame.setBackground(new Color(0, 0, 0, 0));

                } else if (version.startsWith("1.6")) {

                    System.out.println("Transparent from under Java 6");
                    System.out.println("isPerPixelAlphaSupported = " + supportsPerAlphaPixel());
                    setOpaque(frame, false);

                }

                frame.setSize(400, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            }
        });

    }

    public static class MyFrame extends JFrame {

        public MyFrame() throws HeadlessException {

            setContentPane(new MyContentPane());
            setDefaultCloseOperation(EXIT_ON_CLOSE);

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {

                    if (e.getClickCount() == 2) {

                        dispose();

                    }

                }
            });

        }
    }

    public static class MyContentPane extends JPanel {

        public MyContentPane() {

            setLayout(new GridBagLayout());
            add(new JLabel("Hello, I'm a transparent frame under Java " + System.getProperty("java.version")));

            setOpaque(false);

        }

        @Override
        protected void paintComponent(Graphics g) {

            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.BLUE);

            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
            g2d.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);

        }
    }

    public static boolean supportsPerAlphaPixel() {

        boolean support = false;

        try {

            Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
            support = true;

        } catch (Exception exp) {
        }

        return support;

    }

    public static void setOpaque(Window window, boolean opaque) {

        try {

            Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
            if (awtUtilsClass != null) {

                Method method = awtUtilsClass.getMethod("setWindowOpaque", Window.class, boolean.class);
                method.invoke(null, window, opaque);
//                com.sun.awt.AWTUtilities.setWindowOpaque(this, opaque);
//                ((JComponent) window.getContentPane()).setOpaque(opaque);

            }

        } catch (Exception exp) {
        }

    }

    public static void setOpacity(Window window, float opacity) {

        try {

            Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
            if (awtUtilsClass != null) {

                Method method = awtUtilsClass.getMethod("setWindowOpacity", Window.class, float.class);
                method.invoke(null, window, opacity);

            }

        } catch (Exception exp) {

            exp.printStackTrace();

        }

    }

    public static float getOpacity(Window window) {

        float opacity = 1f;
        try {

            Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
            if (awtUtilsClass != null) {

                Method method = awtUtilsClass.getMethod("getWindowOpacity", Window.class);
                Object value = method.invoke(null, window);
                if (value != null && value instanceof Float) {

                    opacity = ((Float) value).floatValue();

                }

            }

        } catch (Exception exp) {

            exp.printStackTrace();

        }


        return opacity;

    }
}

On Windows 7 it produces

Under Java 6 Java6

Under Java 7 Java7

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
3

i guess this will work,i already tried it..to make a JFrame or a window transparent you need to undecorate Undecorated(true) the frame first. Here is sample code :

import javax.swing.*;
import com.sun.awt.AWTUtilities;
import java.awt.Color;   

    class transFrame {
      private JFrame f=new JFrame();
      private JLabel msg=new JLabel("Hello I'm a Transparent Window");

     transFrame() {
       f.setBounds(400,150,500,500);
       f.setLayout(null);
       f.setUndecorated(true);     // Undecorates the Window
       f.setBackground(new Color(0,0,0,25));  // fourth index decides the opacity
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       msg.setBounds(150,250,300,25);
       f.add(msg);
       f.setVisible(true);
      }

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

     }

The only problem is you need to add your own code for close and minimize using buttons.

Rajan Kali
  • 12,627
  • 3
  • 25
  • 37
2

If you want to do it on your own, without using a external lib, you could start a thread that performs :

  • set the transparent window invisible
  • make a Screenshot of the desktop
  • put this screenshot as background image of your window

Or you could use JavaFX

Quick n Dirty
  • 569
  • 2
  • 7
  • 15
  • I cannot do this because the window will follow the mouse, so I'll have to take screenshots every some time, and I think that it's an inefficient method. – Lord Spectre Aug 07 '12 at 11:44
  • and what about using the other option? – Quick n Dirty Aug 07 '12 at 11:48
  • Sorry but I cannot find JavaFX for Linux and JDK 6 – Lord Spectre Aug 07 '12 at 11:58
  • JavaFX for Linux is currently available in [preview form](http://www.oracle.com/technetwork/java/javafx/downloads/devpreview-1429449.html). System requirements in the JavaFX SDK preview for Linux [release notes](http://docs.oracle.com/javafx/2/release_notes_linux/jfxpub-release_notes_linux.htm) state JDK 6u26+ – jewelsea Aug 07 '12 at 17:02
0

I was also facing the same problem. After hours of searching, I finally found the problem! These are the lines you must write, if you want to make a transparent JFrame:

public void enableTransparentWindow(float opacity) {
        GraphicsEnvironment ge =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();

        f.setLocationRelativeTo(null);
        f.setBackground(new Color(0, 0, 0));
        //If translucent windows aren't supported, exit.
        f.setUndecorated(true);

        if (!gd.isWindowTranslucencySupported(TRANSLUCENT)) {
            System.err.println(
                    "Translucency is not supported");
            System.exit(0);
        }
        f.setOpacity(opacity);
    }

Don't forget to call the setVisible() method after this code.
Happy Coding!

MichaelJohn
  • 195
  • 1
  • 2
  • 12