Как удалить тень Java AWT Frame на OSX?

Можно ли отключить тень приложения Java AWT в OS X? Я хочу создать прозрачное окно, которое отлично работает, но я не могу избавиться от тени.

Если бы я использовал JFrame, это можно было бы сделать с помощью:

 JRootPane root = frame.getRootPane();
 root.putClientProperty( "Window.shadow", Boolean.FALSE );

Есть ли аналогичная возможность для AWT Frame?

Я использую Framework Processing, и мой код выглядит так:

void setup(){
  frame.removeNotify();
  frame.setUndecorated(true);
}

Обработка сама создает основной фрейм, вот источник.


person Pwdr    schedule 24.11.2012    source источник


Ответы (3)


Это простое приложение, использующее прозрачное окно, работающее в Max OS X 10.7.5 под Java 7 (запускалось под Java 6), в котором нет проблем...

введите здесь описание изображения

Поделитесь кодом, чтобы мы могли воспроизвести проблему

Обновлено на основе отзывов

Я тестировал это на Mac OS 10.7.5 и 10.8.2, используя JDK 1.7.0_07 и 1.6.0_37.

Без и с Window.shadow свойством...

введите здесь описание изображениявведите здесь описание изображения

Не вдаваясь в многочисленные тесты и не имея дополнительной информации, я бы посоветовал вам сделать этот звонок как можно раньше. Если это не сработает, сделайте это последним вызовом перед тем, как сделать окно видимым.

Это может быть связано с тем, как Java/AWT подключается к своему собственному одноранговому узлу, предположительно, после того, как соединение будет установлено, вы больше не сможете влиять на такие свойства...

public class TransparentFrame {

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

    public TransparentFrame() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }
                // Use this to test the transparentancy API
                //doTransparentFrame();
                doDropShadow();
            }

        });
    }

    protected void doDropShadow() {
        String version = System.getProperty("java.version");
        System.out.println(version);
        JFrame frame = new JFrame("Testing");
        JRootPane root = frame.getRootPane();
        root.putClientProperty("Window.shadow", root);
        frame.setUndecorated(true);
        frame.setContentPane(new ContentPane());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(new ImagePane());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    protected void doTransparentFrame() {
        JFrame frame = new JFrame("Testing");
        frame.setUndecorated(true);
        frame.setContentPane(new ContentPane());

        String version = System.getProperty("java.version");
        System.out.println(version);
        if (version.startsWith("1.7")) {
            frame.setBackground(new Color(0, 0, 0, 0));
        } else if (version.startsWith("1.6")) {
            if (supportsPerAlphaPixel()) {
                setOpaque(frame, false);
            } else {
                System.out.println("Per Pixel Alphering is not support with Java " + version);
                System.exit(1);
            }
        } else {
            System.out.println("Per Pixel Alphering is not support with Java " + version);
            System.exit(1);
        }
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(new ImagePane());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

            }

        } catch (Exception exp) {
        }

    }

    public class ContentPane extends JPanel {

        public ContentPane() {
            setOpaque(false);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
        }

    }

    public class ImagePane extends JPanel {

        private BufferedImage background;
        private BufferedImage offImage;
        private Ellipse2D offButton;
        private boolean mouseIn;

        public ImagePane() {
            setOpaque(false);
            try {
                background = ImageIO.read(new File("tamagotchi400.png"));
                offImage = ImageIO.read(new File("powerSmall.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            offButton = new Ellipse2D.Float(212, 330, 25, 25);
            MouseAdapter handler = new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1) {
                        if (offButton.contains(e.getPoint())) {
                            Window window = SwingUtilities.getWindowAncestor(ImagePane.this);
                            if (window != null) {
                                window.dispose();
                            }
                        }
                    }
                }

                @Override
                public void mouseMoved(MouseEvent e) {
                    Cursor cursor = Cursor.getDefaultCursor();
                    if (offButton.contains(e.getPoint())) {
                        cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
                    }
                    setCursor(cursor);
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    mouseIn = true;
                    repaint();
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    mouseIn = false;
                    repaint();
                }

            };
            addMouseListener(handler);
            addMouseMotionListener(handler);
        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? new Dimension(400, 400) : new Dimension(background.getWidth(), background.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - background.getWidth()) / 2;
                int y = (getHeight() - background.getHeight()) / 2;
                g2d.drawImage(background, x, y, this);
                if (mouseIn && offImage != null) {
                    g2d.drawImage(offImage, (int) offButton.getX(), (int) offButton.getY(), this);
                }
                g2d.dispose();
            }
        }

    }

}

Код также включает код теста прозрачности для тестирования API прозрачности, который теперь доступен в Java 1.7 и Java 1.6_10+. Я успешно использовал этот код в ряде проектов, он менее громоздкий, чем «взлом» робота AWT, и обеспечивает живой фон, но это выбор, который вам нужно сделать.

Обновлено

Демонстрация с использованием java.awt.Frame

введите здесь описание изображения

public class TestTransparentFrame {

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

    public TestTransparentFrame() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception exp) {
                }

                Frame frame = new Frame("Test");
                frame.setUndecorated(true);
                setOpaque(frame, false);
                frame.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {
                        System.exit(0);
                    }

                });
                frame.setLayout(new BorderLayout());
                frame.add(new ContentPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class ContentPane extends JPanel {

        private BufferedImage background;

        public ContentPane() {
            try {
                background = ImageIO.read(new File("duke.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            setOpaque(false);
            JButton close = new JButton("Close");
            close.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    SwingUtilities.getWindowAncestor(ContentPane.this).dispose();
                }
            });
            setBorder(new LineBorder(Color.RED));
            setLayout(new GridBagLayout());
            add(close);
        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                g.drawImage(background, 0, 0, this);
            }
        }

    }

    public static boolean supportsPerAlphaPixel() {

        boolean support = false;
        String version = System.getProperty("java.version");
        if (version.startsWith("1.6")) {
            try {
                Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
                support = true;
            } catch (Exception exp) {
            }
        } else if (version.startsWith("1.7")) {
            try {
                Class<?> winTransClass = Class.forName("java.awt.GraphicsDevice$WindowTranslucency");
                Field field = winTransClass.getField("TRANSLUCENT");

                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice gd = ge.getDefaultScreenDevice();

                gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.TRANSLUCENT);

                Method isWindowTranslucencySupported = GraphicsDevice.class.getMethod("isWindowTranslucencySupported", winTransClass);
                System.out.println(isWindowTranslucencySupported);

                Object value = isWindowTranslucencySupported.invoke(gd, field.get(null));
                if (value instanceof Boolean) {
                    support = ((Boolean) value).booleanValue();
                }

            } catch (Exception exp) {
            }
        }
        return support;
    }

    public static void setOpaque(Window window, boolean opaque) {

        String version = System.getProperty("java.version");
        if (version.startsWith("1.6")) {
            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);
                }
            } catch (Exception exp) {
            }
        } else if (version.startsWith("1.7")) {
            Color color = UIManager.getColor("Panel.background");
            if (opaque) {
                color = new Color(color.getRed(), color.getGreen(), color.getBlue());
            } else {
                color = new Color(color.getRed(), color.getGreen(), color.getBlue(), 0);
            }
            window.setBackground(color);
        }

    }

}

Протестировано в Windows 7 Java 1.6 и 1.7, Mac OS 10.7.5 и 10.8.2 с использованием JDK 1.7.0_07 и 1.6.0_37

Похоже, вы не понимаете иерархию окон в Java.

Все «окна» в Java происходят от java.awt.Window.

JFrame расширяет Frame, который расширяет Window.

person MadProgrammer    schedule 25.11.2012
comment
Нет проблем, я просто не знаю, как избавиться от тени в белом кадре AWT. - person Pwdr; 26.11.2012
comment
Я использую прозрачные рамки на Mac OS без особого смысла, они не отображают тень. Можете ли вы поделиться некоторым кодом, чтобы мы могли видеть, как вы создаете свое окно, и чтобы мы могли его воспроизвести, таким образом, мы могли бы помочь еще немного - person MadProgrammer; 26.11.2012
comment
Таким образом, ваш пример кода будет создавать не прозрачную рамку, а бескаркасную. - person MadProgrammer; 28.11.2012
comment
Да, я показываю скриншот рабочего стола, который выглядит прозрачным. Существуют также функции для создания прозрачного кадра с помощью AWTUtilities, но эти функции предназначены только для окон. Используя метод скриншота, у меня работает создание прозрачной рамки ... кроме тени. - person Pwdr; 28.11.2012
comment
Аааа... теперь куда денешься ;) - person MadProgrammer; 28.11.2012
comment
но эти функции только для Windows - Если вы имеете в виду MS Windows, то нет, они отлично работают на Mac OS. Если вы имеете в виду java.awt.Window, то да, но JFrame происходит от java.awt.Window ;) - person MadProgrammer; 28.11.2012
comment
Да, но вы говорите здесь о JFrame, функциональность необходима для фрейма (без Swing). - person Pwdr; 29.11.2012
comment
Хорошо, справедливо, я пропустил это... однако метод AWTUtilities#setWindowOpacity в Java 6 принимает Window, из которого Frame расширяется. С этой точки зрения вы можете получить прозрачную рамку, не прибегая к хаку Robot. Мне нужно будет проверить цвет фона. - person MadProgrammer; 29.11.2012
comment
Я все еще тестирую, но под Java 7 и Java 6 под Windows я могу сделать Frame прозрачным. Мне нужно будет протестировать его на своих компьютерах Mac, когда я вернусь домой. - person MadProgrammer; 29.11.2012
comment
Теперь протестировано и продемонстрировано с использованием java.awt.Frame - person MadProgrammer; 29.11.2012

Используя эту строку, он работает:

AWTUtilities.setWindowOpaque(frame, false);

Eclipse выводит предупреждение об этом, и мне пришлось изменить некоторые настройки, чтобы скомпилировать его, поэтому я думаю, что могут быть лучшие способы. Я прочитал здесь, что это поддерживается, поскольку ОС Х 10,6 (Лев).

person Pwdr    schedule 29.11.2012

Кажется, что когда ваш кадр не в фокусе, сработает эффект тени. Попробуйте добавить этот код, чтобы ваш кадр был отключен в фокусе.

frame.setFocusableWindowState(false);
person JayLord Abueva    schedule 03.09.2020