jframe的自定义透明背景出错

hsvhsicv  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(271)

我已经尝试了好几天了,读了这么多的解释,但正如我试图应用它们,似乎没有任何工作。
我需要做的是创建一个自定义形状的窗口。我想要的方法是将窗口背景设置为如下图像:

我尝试实现这一点的方法大体上就是这里描述的方法https://stackoverflow.com/a/13594794/1387451
但这不太管用。相反,它看起来就像java将我的背景解释为alpha掩码:白色变为不透明,黑色变为透明。我认为java可以做到这一点非常棒,但这不是我所需要的。
我试着玩弄我眼睛的不透明 JFrame 的内容窗格。没有什么。我试着用 JLabel 或者 JPanel 对于图像没有用。
请帮我破译这个。
这是相关代码。
这个 JFrame :

public class LectorWindow extends JFrame {

    public LectorWindow() {
        Dimension winSize = new Dimension(440, 80);
        LectorDraggerListener dragger = new LectorDraggerListener(this);
        addMouseListener(dragger);
        addMouseMotionListener(dragger);

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        setUndecorated(true);
        setBackground(new Color(0f, 0f, 0f, 0f));
        setContentPane(new TransparentContentPane());

        setSize(winSize);
        int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
        setLocation(screenWidth/2 - getWidth()/2, 0);

        setLayout(new BorderLayout());

        JPanel background = new BackgroundPanel();
        background.setLayout(new BoxLayout(background, BoxLayout.X_AXIS));
        add(background);

        setResizable(false);
        setAlwaysOnTop(true);

        setUpSysTray();

        setVisible(true);
    }
}

内容窗格:

public class TransparentContentPane extends JPanel {

    private static final long serialVersionUID = -386560825154911212L;

    public TransparentContentPane() {
        setOpaque(false);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.RED);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
}

以及背景图像 JPanel :

public final class BackgroundPanel extends JPanel {

    private static final long serialVersionUID = -5526340149401796784L;

    private BufferedImage background;

    public BackgroundPanel() {
        try {
            background = ImageIO.read(BackgroundPanel.class.getResource("/lector/resources/background.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        setOpaque(false);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(background.getWidth(), background.getHeight());
    }

    @Override
    public 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);
            g2d.dispose();
        }
    }
}

我在启用窗口合成的xfce上使用openjdk(我试图禁用它,但后来一切变得更奇怪)。我想让它在Java7上运行,我不关心Java6。
下面是我的两个程序的截图:

内容窗格被漆成红色。

contentpane只是一个普通的 JPanelsetOpaque(false) . (我们为什么要把它涂成红色?)

ioekq8ef

ioekq8ef1#

真的只有两件事需要做 setOpaque(false) 对于具有图像的面板。 setBackground(new Color(0, 0, 0, 0)) 对于帧,最后0是alpha
奖励:为了增加情趣,我加了一个 MouseMotionListener 所以你仍然可以移动它:)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ImageFrame {
    private final JFrame frame = new JFrame();
    public ImageFrame() {
        frame.setUndecorated(true);
        frame.setBackground(new Color(0, 0, 0, 0));
        frame.add(new BackGroundPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public class BackGroundPanel extends JPanel {

        BufferedImage image;
        int pX, pY;

        public BackGroundPanel() {
            try {
                image = ImageIO.read(new URL("http://i.stack.imgur.com/efS42.png"));
            } catch (IOException ex) {
                Logger.getLogger(ImageFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
            setOpaque(false);

            addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent me) {
                    // Get x,y and store them
                    pX = me.getX();
                    pY = me.getY();
                }
            });
            addMouseMotionListener(new MouseAdapter() {
                public void mouseDragged(MouseEvent me) {
                    frame.setLocation(frame.getLocation().x + me.getX() - pX, 
                            frame.getLocation().y + me.getY() - pY);
                }
            });
        }

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

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

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new ImageFrame();
            }
        });
    }
}

编辑
我只是试了一下你的代码,如果你摆脱了 TransparentContentPane 作为内容窗格。我不知道那是干什么用的?

相关问题