3

由于显示 JAVA 6 启动画面的问题,我使用以下方法显示启动窗口。

File splashImageFile = new File(Constants.PATH_IMAGE + "splash.png");
        final BufferedImage img = ImageIO.read(splashImageFile);
        final JWindow window = new JWindow() {
            private static final long serialVersionUID = -132452345234523523L;

            @Override
            public void paint(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
                Rectangle windowRect = getBounds();
                try {
                    Robot robot = new Robot(getGraphicsConfiguration().getDevice());                        
                    BufferedImage capture = robot.createScreenCapture(new Rectangle(windowRect.x, windowRect.y, windowRect.width, windowRect.height));
                    g2.drawImage(capture, null, 0, 0);
                } catch (IllegalArgumentException iae) {
                    System.out.println("Argumets mis matched.\n" + iae.getMessage());
                } catch(SecurityException se){
                    System.out.println("Security permission not supported\n" + se.getMessage());
                } catch (AWTException ex) {
                    System.out.println("Exception found when creating robot.\n" + ex.getMessage());
                }
                g2.drawImage(img, 0, 0, null);
                g2.setFont(new Font("TimesRoman", Font.BOLD, 15));
                g2.drawString("Loading...", 320, 260);
                g2.dispose();
            }
        };
        window.setAlwaysOnTop(true);
        window.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
        window.pack();
        window.setLocationRelativeTo(null);
        window.setVisible(true);
        window.repaint();

该图像是 png 透明图像,因为我的窗口中需要圆角矩形。它适用于 Win 7,但适用于 mac 10.8。Mac 仍然显示矩形形状背景。它实际上也不是背景。有人可以告诉我可能导致的原因。以下是每个平台的图像。

在窗户上

视窗

在 Mac 上

苹果电脑

提前致谢。

编辑:

答案很好,但我发现 AWTUtilities 并不总是得到系统支持。因此,在某些系统中,应答方法可能会失败。没有一个很正式的解决方案吗?我的意思是解决方案来自基层?

4

4 回答 4

6

http://docs.oracle.com/javase/tutorial/uiswing/misc/trans_shape_windows.html#shape 这显示了如何创建形状窗口

addComponentListener(new ComponentAdapter() {
            // Give the window an elliptical shape.
            // If the window is resized, the shape is recalculated here.
            @Override
            public void componentResized(ComponentEvent e) {
                setShape(new Ellipse2D.Double(0,0,getWidth(),getHeight()));
            }
        });

        setUndecorated(true);

他们说:从 Java Platform, Standard Edition 6 (Java SE 6) Update 10 发布开始,您可以向您的 Swing 应用程序添加半透明和形状的窗口。

于 2012-10-29T12:38:35.970 回答
5

如前所述,从 Java 1.6 更新 10 开始,您可以访问com.sun.awt.AWTUtilities(私有 API),该 API 提供每像素 alphaering 支持。

在此处输入图像描述

所有这一切的技巧之一是确保将内容窗格也设置为透明。

在 Mac OS 10.7.5、10.8.2 下测试;使用 Java 1.6.0_37 和 1.7.0_06

public class TestWindowTransparency {

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

    public TestWindowTransparency() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                SplashWindow window = new SplashWindow();
                window.setVisible(true);

            }
        });

    }

    public class SplashWindow extends JWindow {

        public SplashWindow() {

            ImageIcon icon = null;

            try {
                icon = new ImageIcon(ImageIO.read(getClass().getResource("/Splash02.png")));
            } catch (Exception e) {
                e.printStackTrace();
            }

            setAlwaysOnTop(true);
            JPanel content = new JPanel(new BorderLayout());
            content.setOpaque(false);
            setContentPane(content);

            JLabel lbl = new JLabel(icon);
            lbl.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        dispose();
                    }
                }
            });

            add(lbl);

            if (!supportsPerAlphaPixel()) {
                System.out.println("Per Pixel Alpher is not supported by you system");
            }

            setOpaque(false);

            pack();
            setLocationRelativeTo(null);

        }

        public boolean supportsPerAlphaPixel() {
            boolean support = false;
            try {
                Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
                support = true;
            } catch (Exception exp) {
                exp.printStackTrace();
            }
            return support;
        }

        public void setOpaque(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, this, opaque);
                }
            } catch (Exception exp) {
                exp.printStackTrace();
            }
        }

        public void setOpacity(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, this, opacity);
                }
            } catch (Exception exp) {
                exp.printStackTrace();
            }
        }

        public float getOpacity() {
            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, this);
                    if (value != null && value instanceof Float) {
                        opacity = ((Float) value).floatValue();
                    }
                }
            } catch (Exception exp) {
                exp.printStackTrace();
            }
            return opacity;
        }
    }
}
于 2012-11-01T08:59:03.297 回答
4

要获得统一的解决方案,您应该使用 Java7。每像素半透明几乎是 Java 6 中的一个“实验性”功能,并且不被认为是您可以依赖的东西(这就是为什么 AWTUtilities 包含在 com.sun 包中,它不是 Java 公共 API 的一部分)。

然而,虽然我没有 Mac 来测试它,但我看到有人报告说在 MacOS 中将框架背景设置为 Color(0, 0, 0, 0) (最后一个参数是 alpha 通道)对他们有用. 我不清楚它是否在 Windows 中工作(几年前我不得不使用它),但我刚刚在 Linux 中测试过它并没有。

在 Java 7 中,完全支持半透明窗口并在 Windows、MacOS 和 Linux 中完美运行。JFrame 具有新的 setOpacity(Alpha) 方法(仅适用于未修饰的帧)并且 setColor(new Color(R, G, B, Alpha)) 也可以工作(它是等效的,并且再次仅适用于未修饰的帧)。

如您所见,您不能依赖私有 API AWTUtilities。在 Java 6 中,您没有针对此问题的任何“正式解决方案”,只有 hack、私有 API 和不确定性……我不知道这是否是一种选择,但如果可以的话,您应该考虑切换到 Java7。

于 2012-11-04T17:04:18.230 回答
2

正如我所说,某些系统可能不支持使用 AWTUtilities,必须同意 Eneko。我也这样做了,如下所示。似乎有点类似于eneko的想法。我已经在 windows 7 终极版和苹果 mac os 雪豹中测试过了。它对两者都有效。同样,如果这在 linux 上不起作用,那么这也不是一个广泛适用的解决方案。希望有人可以发布该答案。

final JWindow window = new JWindow() {
            private static final long serialVersionUID = -132452345234523523L;

            @Override
            public void paint(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                Rectangle windowRect = new Rectangle(getSize());
                g2.setColor(new Color(255, 255, 255, 0));
                g2.draw(new RoundRectangle2D.Float(windowRect.x, windowRect.y, windowRect.width, windowRect.height, 85, 85));
                g2.drawImage(img, 0, 0, null);
                g2.dispose();
            }
        };            
        window.setBackground(new Color(0,0,0,0));
于 2012-11-04T17:19:23.500 回答