使用图像的java自定义形状框架

使用图像的java自定义形状框架,java,swing,jframe,Java,Swing,Jframe,我喜欢创建一个类似于此图像的java jframe。我已经用不同的形状(如三角形、圆形、多边形和一些疯狂的形状)包装了jframe。但问题是,要创建类似此图像的形状太难了[99%不可能]。因此,我如何才能创建这样的jframe。我使用此代码创建了形状窗口 setUndecorated(true); Polygon polygon = new Polygon(); polygon.addPoint(0, 0); polygon.addPoint(100,100); GeneralPath pat

我喜欢创建一个类似于此图像的java jframe。我已经用不同的形状(如三角形、圆形、多边形和一些疯狂的形状)包装了jframe。但问题是,要创建类似此图像的形状太难了[99%不可能]。因此,我如何才能创建这样的jframe。我使用此代码创建了形状窗口

setUndecorated(true);
Polygon polygon = new Polygon();
polygon.addPoint(0, 0);
polygon.addPoint(100,100);

GeneralPath path = new GeneralPath();
path.append(polygon, true);
setShape(path);
现在我可以把这个图像转换成一个形状。然后设置形状。有什么想法吗?
或者,是否有任何方法可以使jframe的完全透明和可伸缩,从而使图像完全可见?

您必须根据图像创建一个形状。这里有不同的线程,因此提供了一些方法来实现这一点。最好的(根据描述,我自己没有试过)可能是。对于更复杂的图像,另一种选择是


另一个解决方案可能是使用未装饰的框架和“每像素透明度”,正如Oracle在这里解释的那样:

您必须根据图像创建形状。这里有不同的线程,因此提供了一些方法来实现这一点。最好的(根据描述,我自己没有试过)可能是。对于更复杂的图像,另一种选择是


另一种解决方案可能是使用未装饰的帧以及“每像素透明度”,正如Oracle在这里解释的那样:

要制作透明窗口,需要将帧背景颜色的alpha设置为
0
。这可能是我在一段时间内看到的最违反直觉的调用,如果对任何其他Swing组件执行此操作,则会完全破坏绘制过程

您不希望更改窗口的不透明度,因为它会对整个窗口及其内容产生同等效果

例如

JWindow frame = new JWindow();
frame.setBackground(new Color(0, 0, 0, 0));
您不必使用
JWindow
,但这意味着我不需要自己去装饰它

您还需要确保添加到窗口中的任何内容都是透明的(不透明=假),这样它就不会“隐藏”它下面的内容

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class LeafWindow {

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

    public LeafWindow() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JWindow frame = new JWindow();
                frame.setBackground(new Color(0, 0, 0, 0));
                frame.setContentPane(new LeafPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                frame.setAlwaysOnTop(true);
            }
        });
    }

    public class LeafPane extends JPanel {

        private BufferedImage leaf;

        public LeafPane() {

            setBorder(new CompoundBorder(
                            new LineBorder(Color.RED),
                            new EmptyBorder(0, 0, 250, 0)));

            try {
                leaf = ImageIO.read(getClass().getResource("/Leaf.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            setOpaque(false);
            setLayout(new GridBagLayout());

            JButton button = new JButton("Close");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });

            add(button);

        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (leaf != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.drawImage(leaf, 0, 0, this);
                g2d.dispose();
            }
        }
    }

}


此示例向内容添加了一个线条边框,因为您可以看到原始窗口边框是什么。它还使用
EmptyBorder
JButton
强制到图形上,但这只是一个示例…

要创建透明窗口,需要将帧背景颜色的alpha设置为
0
。这可能是我在一段时间内看到的最违反直觉的调用,如果对任何其他Swing组件执行此操作,则会完全破坏绘制过程

JWindow frame = new JWindow();
frame.setBackground(new Color(0, 0, 0, 0));
您不希望更改窗口的不透明度,因为它会对整个窗口及其内容产生同等效果

例如

JWindow frame = new JWindow();
frame.setBackground(new Color(0, 0, 0, 0));
您不必使用
JWindow
,但这意味着我不需要自己去装饰它

您还需要确保添加到窗口中的任何内容都是透明的(不透明=假),这样它就不会“隐藏”它下面的内容

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class LeafWindow {

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

    public LeafWindow() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JWindow frame = new JWindow();
                frame.setBackground(new Color(0, 0, 0, 0));
                frame.setContentPane(new LeafPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                frame.setAlwaysOnTop(true);
            }
        });
    }

    public class LeafPane extends JPanel {

        private BufferedImage leaf;

        public LeafPane() {

            setBorder(new CompoundBorder(
                            new LineBorder(Color.RED),
                            new EmptyBorder(0, 0, 250, 0)));

            try {
                leaf = ImageIO.read(getClass().getResource("/Leaf.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            setOpaque(false);
            setLayout(new GridBagLayout());

            JButton button = new JButton("Close");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });

            add(button);

        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (leaf != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.drawImage(leaf, 0, 0, this);
                g2d.dispose();
            }
        }
    }

}


此示例向内容添加了一个线条边框,因为您可以看到原始窗口边框是什么。它还使用
EmptyBorder
JButton
强制到图形上,但这只是一个示例…

老实说,如果使用透明帧并将图像绘制到背景中,将获得更好的效果,您将获得抗锯齿效果,而不是锐利的像素下降。通过一些巧妙的工作,如果需要,还可以生成一个剪切矩形it@MadProgrammer当我搜索的时候,我找到了很多你回答的答案。你能再解释一下怎么做吗?我不需要代码,只需要过程。我的英语不流利。我尝试将“帧不透明度”设置为0。但所有帧均隐藏。我尝试将“不透明”设置为false。我记得我是用c#使用透明键做的。但是我仍然没有找到一种方法使窗口透明,图像完全可见。对不起,应该是不要改变不透明度,因为它会影响框架和内容。相反,您希望将帧背景颜色的alpha设置为0,并使添加到其中的内容透明(不透明=假)。我添加了一个可运行的示例来演示,并稍加解释……老实说,使用透明帧并将图像绘制到背景中,您将获得更好的效果,您将获得抗锯齿效果,而不是急剧下降的像素。通过一些巧妙的工作,如果需要,还可以生成一个剪切矩形it@MadProgrammer当我搜索的时候,我找到了很多你回答的答案。你能再解释一下怎么做吗?我不需要代码,只需要过程。我的英语不流利。我尝试将“帧不透明度”设置为0。但所有帧均隐藏。我尝试将“不透明”设置为false。我记得我是用c#使用透明键做的。但是我仍然没有找到一种方法使窗口透明,图像完全可见。对不起,应该是不要改变不透明度,因为它会影响框架和内容。相反,您希望将帧背景颜色的alpha设置为0,并使添加到其中的内容透明(不透明=假)。我添加了一个可运行的示例进行演示,并提供了更多的解释……非常感谢。太棒了……您玩得很开心,很高兴它有所帮助;)非常感谢。那太棒了。你会玩得很开心,很高兴它帮了你;)
JWindow frame = new JWindow();
frame.setBackground(new Color(0, 0, 0, 0));