简体   繁体   中英

Splash window does not work in mac

Due problems in showing JAVA 6 Splash screen i used following method to show a splash window.

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

The image is png transparent image as i need rounded cornered rectangle shape in my window. It works on Win 7 but in mac 10.8. Mac still shows rectangle shape background. It does not seems as background either actually. Can someone tell me what may cause to that. Following are the images for each platform.

On windows

视窗

On mac

苹果电脑

Thanks in advance.

EDIT:

Answers are great but I've seen that AWTUtilities is not always getting system support. So in some some systems answered methods may fail. Isn't there a solution much formal? I mean solution comes from the basic level?

http://docs.oracle.com/javase/tutorial/uiswing/misc/trans_shaped_windows.html#shaped This shows how to create shaped window

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

They said: As of the Java Platform, Standard Edition 6 (Java SE 6) Update 10 release, you can add translucent and shaped windows to your Swing applications.

As has already begin stated, as of Java 1.6 update 10, you have access to com.sun.awt.AWTUtilities (a private API) which provides per pixel alphaering support.

在此输入图像描述

One of the tricks to all this, is making sure you set the content pane to transparent as well.

Tested under Mac OS 10.7.5, 10.8.2; using Java 1.6.0_37 and 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;
        }
    }
}

To get an uniform solution, you should use Java7. Per pixel translucency was nearly an "experimental" feature in Java 6, and not thought to be something you could rely on (that's why AWTUtilities was into the com.sun package, which is not part of Java public API ).

However, and although I haven't got a Mac to test it, I've seen people reporting that setting the frame background to Color(0, 0, 0, 0) (last parameter is the alpha channel) worked for them in MacOS. I do not remember clearly if it worked in windows (I had to use it a couple of years ago), but I've just tested it in Linux and it doesn't.

In Java 7, translucent windows are fully supported and working flawlessly in Windows, MacOS and Linux. JFrame has the new setOpacity(Alpha) method (that works only with undecorated frames) and setColor(new Color(R, G, B, Alpha)) is also working (it's equivalent, and again only working with undecorated frames).

As you can see, you can't rely on the private API AWTUtilities. In Java 6 you haven't got any "formal solution" for this problem, only hacks, private APIs and uncertainty... I don't know if it is an option, but you should think about switching to Java7 if you can.

As i said using AWTUtilities may not supported by certain system and have to agree with Eneko. Also i've done this as follows. Seems somewhat similar to idea of eneko. I've tested it in windows 7 ultimate edition and apple mac os snow leopard. It worked on both. Again if this not work on linux then this also not a widely applicable solution. Wish someone can post that answer.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM