【问题标题】:Java transparent windowJava透明窗口
【发布时间】:2012-08-04 09:45:36
【问题描述】:

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

我用 Python 和 Qt 来做这件事(参见 Python overlay window),但后来我改用了 Java 和 Swing。但是我无法使窗口透明。我试过this method,但它不起作用,但我认为我的系统支持透明度,因为如果我启动Screencast-O-Matic(在Java中),矩形实际上是透明的。

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

【问题讨论】:

  • 你有解决这个问题的办法吗?我面临同样的问题..我已经制作了像 Screencast-O-Matic 这样的应用程序,它适用于 Windows 操作系统,但不适用于 Linux..如果你发现任何东西,请在这里提出建议,stackoverflow.com/questions/25009276/…
  • 不,我为我的截屏应用程序切换回 PyQt,因为我在 Java 方面遇到了其他问题。

标签: java linux swing window transparent


【解决方案1】:

为什么 Java 教程How to Create Translucent and Shaped Windows 失效了?您使用的是最新版本的 Java 6 还是 Java 7? 在May/June issue of Java Magazine 中,有一个关于需要Java 7 的形状和透明窗口的教程。您可能需要注册Java 杂志才能阅读它。看看你是否可以让它在你的系统上运行:

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

【讨论】:

  • 我使用的是 Java 6,这就是我使用页面底部的兼容性方法的原因...以您的示例,我得到 this
  • 好的。您站点的 Java 教程需要 Java 6 更新 10,所以只要您拥有它,它应该可以工作。如果没有,那么一定是 linux 兼容性问题,在这种情况下,我建议您升级到 JDK 7,看看是否能解决问题。
【解决方案2】:

如果您使用的是 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 下

在 Java 7 下

【讨论】:

  • 我做了,另一个它甚至没有编译
  • 我不确定您的意思,请查看我的示例
  • 我在 Java 6 上,它只用 AWTUtilities 编译,但运行时没有透明度。
  • 听起来像是您在更新 10 之前运行的 Java 版本,或者它不受支持。检查java.sun.com/developer/technicalArticles/GUI/…,其中有示例代码以确定可用的内容
【解决方案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();
      }

     }

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

【讨论】:

    【解决方案4】:

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

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

    或者你可以使用JavaFX

    【讨论】:

    • 我不能这样做,因为窗口会跟随鼠标,所以我必须每隔一段时间截屏一次,我认为这是一种低效的方法。
    • 那么使用其他选项呢?
    • 抱歉,我找不到适用于 Linux 和 JDK 6 的 JavaFX
    • JavaFX for Linux 目前在preview form 中可用。适用于 Linux release notes 状态 JDK 6u26+ 的 JavaFX SDK 预览版中的系统要求
    【解决方案5】:

    我也遇到了同样的问题。经过几个小时的搜索,我终于找到了问题!如果你想制作一个透明的 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() 方法。
    快乐编码!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多