【问题标题】:Splash window does not work in mac启动窗口在 mac 中不起作用
【发布时间】:2012-10-27 10:39:43
【问题描述】:

由于显示 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 并不总是获得系统支持。因此,在某些系统中,应答方法可能会失败。没有一个很正式的解决方案吗?我的意思是解决方案来自基层?

【问题讨论】:

    标签: java swing user-interface splash-screen


    【解决方案1】:

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

    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 平台标准版 6 (Java SE 6) Update 10 版本开始,您可以向 Swing 应用程序添加半透明和成形窗口。

    【讨论】:

    • 这不是最好的方法。生成的形状窗口未进行抗锯齿处理,并且边框呈锯齿状。这可以通过使用每像素半透明来避免;你可以在框架背景上绘制任何你想要的东西,不管它是 png 还是 Java2D 的抗锯齿椭圆。
    【解决方案2】:

    如前所述,从 Java 1.6 更新 10 开始,您可以访问 com.sun.awt.AWTUtilities(一个私有 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;
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

        正如我所说,某些系统可能不支持使用 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));
        

        【讨论】:

        • 你刚刚违反了油漆链的要求。您需要调用super.paint 以确保正确绘制组件,这在处理透明度时尤其重要。一个更简单的解决方案是用您自己的透明窗格替换内容窗格并使用paintComponent 对其进行绘画 - 恕我直言
        猜你喜欢
        • 2017-10-28
        • 1970-01-01
        • 2018-12-15
        • 1970-01-01
        • 1970-01-01
        • 2014-12-23
        • 1970-01-01
        • 2018-06-06
        • 2010-09-24
        相关资源
        最近更新 更多