Java transparent window

2019-01-19 01:11发布

问题:

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)

回答1:

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);
        }
    }
}


回答2:

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

Under Java 7



回答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.



回答4:

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