3

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

谢谢你的时间。

4

3 回答 3

9

我个人会放弃窗口形状,转而使用透明窗口,这对你想要做的事情来说更简单......

在此处输入图像描述

并使用关闭按钮(查看左下角)

在此处输入图像描述

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

这依赖于 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();
            }
        }
    }
}
于 2012-11-27T23:02:41.547 回答
3

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

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

于 2012-11-27T16:41:24.173 回答
0

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

frame.setBackground(new Color(0, 0, 0, 0));
于 2015-03-10T11:00:19.857 回答