【问题标题】:JFrame the same shape as an Image / Program running in backgroundJFrame与后台运行的图像/程序具有相同的形状
【发布时间】:2016-07-28 23:53:26
【问题描述】:

我的问题很简单,解决方案肯定不是。我正在寻找一种将 JFrame 塑造成与它将显示的图像相同的方法。形状是指具有 alpha != 0 的像素的形状。我已经找到了一个使用 GeneralPath 对象的工作示例,但它为大约 500*400 的图像创建了约 110000 个“节点”,因此开始JFrame用了2多分钟,肯定不是想要的效果,启动应该在2秒以内。

感谢您的宝贵时间。

【问题讨论】:

标签: java image swing jframe shape


【解决方案1】:

我个人会放弃窗口形状以支持透明窗口,这对于您想要做的事情来说更简单......

还有关闭按钮(看左下角)

图像周围的红色边框是故意的,因为它显示了“窗口”边界。

这依赖于 Java 1.7 或 Java 1.6_10+,代码中有检查。

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) {
                }

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

【讨论】:

  • +1 非常好的例子,但我必须问你为什么要通过检查 java 版本和类等来检查每个像素的半透明度,isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT) 会更好地看到here
  • @DavidKroukamp isWindowTranslucencySupported 仅在 Java 7 中受支持。在 Java 6 下我需要遵循不同的 API 路径,但是它仅在 Java 1.6 更新 10 之后可用,因此使用反射。在 Java 7 下,我实际上也应该使用 isWindowTranslucencySupported,我会努力将它添加到我的库代码中,干杯:D
【解决方案2】:

我无法理解您的第一个问题。我的英语不太好,这可能是原因。

关于第二个问题,你有没有尝试过关于 TrayIcon 的东西?请看:http://docs.oracle.com/javase/tutorial/uiswing/misc/systemtray.htmlhttp://docs.oracle.com/javase/6/docs/api/java/awt/TrayIcon.html

【讨论】:

  • 谢谢,但我已经找到了您发布的那些链接。关于第一个问题:假设我正在制作类似 PC-Tamagotchi 的东西。为此,我有一个形状像“oldschool” Tamagotchi 控制器的背景图像。该图像是非矩形的,我不希望在图像周围看到 JFrame 轮廓。这就是为什么我需要 JFrame 来适应图像。
  • 异形框架不会显示边框或标题栏(因为你已经剪掉了框架),我个人认为你最好使用透明框架
  • @MadProgrammer 想如果那样,为什么 OP 不只是创建透明框架,从而使电子鸡的界面可见而 Jframe 的背景不可见。 +1 好建议
  • @MadProgrammer 如果您查看诸如星际争霸 2 之类的安装菜单,会想得更多可能实现?
  • @DavidKroukamp 不在我的电脑前,我到那里会看演示 ;)
【解决方案3】:

只需在 JFrame 中添加新的标签图像 然后 设置 Jframe 背景透明

frame.setBackground(new Color(0, 0, 0, 0));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 2023-03-24
    • 1970-01-01
    • 2023-01-10
    • 2020-01-23
    • 2021-08-25
    • 2017-09-09
    相关资源
    最近更新 更多