9

我正在尝试创建一个跟随鼠标并将点击传递给底层窗口的圆形窗口。

我用 Python 和 Qt 做这个(见Python 覆盖窗口),但后来我切换到 Java 和 Swing。但是我无法使窗口透明。我尝试了这种方法,但它不起作用,但是我认为我的系统支持透明度,因为如果我启动Screencast-O-Matic(在 Java 中),矩形实际上是透明的。

我怎样才能实现这样的目标?(我在 Linux KDE4 上)

4

5 回答 5

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);
        }
    }
}
于 2012-08-07T12:01:46.953 回答
4

如果您使用的是 Java 6,则需要使用私有 API AWTUtilities。查看Java SE 6 Update 10 API了解更多详情

例子

这是一个快速的技巧,但它让想法得到了理解

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;

    }
}

在 Windows 7 上它产生

在 Java 6 下 Java6

在 Java 7 下 Java7

于 2012-08-07T20:32:41.797 回答
3

我想这会起作用,我已经尝试过了..要使 JFrame 或窗口透明,您需要先取消装饰Undecorated(true)框架。这是示例代码:

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

     }

唯一的问题是您需要添加自己的代码以使用按钮关闭和最小化。

于 2014-01-09T02:47:46.453 回答
2

如果你想自己做,不使用外部库,你可以启动一个线程来执行:

  • 设置透明窗口不可见
  • 制作桌面截图
  • 将此屏幕截图作为窗口的背景图像

或者你可以使用JavaFX

于 2012-08-07T11:39:44.230 回答
0

我也面临同样的问题。经过几个小时的搜索,我终于找到了问题!如果你想制作一个透明的 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);
    }

不要忘记在这段代码之后调用 setVisible() 方法。
快乐编码!

于 2021-09-03T22:54:34.033 回答