Заставка не работает в Mac

Из-за проблем с отображением заставки 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();

Это прозрачное изображение, так как мне нужно, чтобы в моем окне была прямоугольная форма с закругленными углами. Это работает на Win 7, но в Mac 10.8. Mac по-прежнему показывает прямоугольник формы фона. На самом деле это не выглядит как фон. Может кто-нибудь сказать мне, что может быть причиной этого. Ниже приведены изображения для каждой платформы.

На окнах

окна

На макинтош

макинтош

Заранее спасибо.

РЕДАКТИРОВАТЬ:

Ответы отличные, но я видел, что AWTUtilities не всегда получает поддержку системы. Таким образом, в некоторых системах ответные методы могут давать сбой. Разве не существует решения, формального? Я имею в виду решение приходит с базового уровня?

4 ответа

Решение

Чтобы получить единое решение, вы должны использовать Java7. Полупрозрачность на пиксель была почти "экспериментальной" функцией в Java 6, и не считалось, что на нее можно положиться (именно поэтому AWTUtilities входит в пакет com.sun, который не является частью общедоступного API Java).

Тем не менее, и хотя у меня нет Mac для его тестирования, я видел людей, сообщавших, что установка фона рамки в Color(0, 0, 0, 0) (последний параметр - альфа-канал) работает для них в MacOS, Я не помню четко, работал ли он в Windows (мне пришлось использовать его пару лет назад), но я только что проверил его в Linux, и это не так.

В Java 7 полупрозрачные окна полностью поддерживаются и работают безупречно в Windows, MacOS и Linux. JFrame имеет новый метод setOpacity(Alpha) (который работает только с неокрашенными кадрами), и setColor(новый цвет (R, G, B, Alpha)) также работает (это эквивалентно, и снова работает только с неокрашенными кадрами).

Как видите, вы не можете полагаться на закрытый API AWTUtilities. В Java 6 у вас нет никакого "формального решения" этой проблемы, только хаки, частные API и неопределенность... Я не знаю, если это вариант, но вы должны подумать о переходе на Java7, если можете.

http://docs.oracle.com/javase/tutorial/uiswing/misc/trans_shaped_windows.html Это показывает, как создать фасонное окно

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), обновление 10, вы можете добавлять полупрозрачные и фигурные окна в свои приложения Swing.

Как уже говорилось, начиная с Java 1.6 update 10, вы имеете доступ к com.sun.awt.AWTUtilities (частный API), который обеспечивает поддержку альферинга на пиксель.

Один из приемов всего этого - убедиться, что вы установили прозрачную панель содержимого.

Протестировано под 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;
        }
    }
}

Как я уже сказал, использование AWTUtilities может не поддерживаться определенной системой и должно быть согласовано с Eneko. Также я сделал это следующим образом. Кажется, что-то похожее на идею eneko. Я проверил это в Windows 7 Ultimate Edition и Apple Mac OS Snow Leopard. Это сработало на обоих. Опять же, если это не работает на 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));
Другие вопросы по тегам