java - JFrame 与在后台运行的图像/程序具有相同的形状

标签 java image swing jframe shapes

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

感谢您的宝贵时间。

最佳答案

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

enter image description here

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

enter image description here

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

这依赖于 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();
            }
        }
    }
}

关于java - JFrame 与在后台运行的图像/程序具有相同的形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13588786/

相关文章:

JScrollPane 中的 Java JPanel?

java - JPanel 将自身绘制在 JFrame 标题栏下方

java - 如何在空布局中设置jpanel的大小

java - 直接在 Android 适配器中更改日期格式

java - 使用与当前相同的可执行文件启动 Java 进程

c# - 如何在 C# 的 Web 应用程序中从服务器加载图像

c# - Python 中不安全的图像处理,如 C# 中的 LockBits

java - 在 jpanel 上绘制字符串

java - 成员类访问修饰符

html - 图像重复不起作用,为什么...?