java - JFrame 自定义透明背景出错

标签 java swing user-interface

我几天来一直在努力解决这个问题,阅读了很多解释,但当我尝试应用它们时,似乎没有任何效果。

我需要做的是创建一个自定义形状的窗口。我想要的方法是将窗口背景设置为如下图像: Not like this one, but actually this one.

总的来说,我用来尝试实现这一目标的方法是此处描述的方法 https://stackoverflow.com/a/13594794/1387451

但它不太有效。相反,它看起来好像 java 将我的背景解释为 alpha 蒙版:白色变得不透明,黑色变得透明。 我认为 java 能做到这一点非常棒,但这不是我需要的。

我尝试调整 JFrame 内容 Pane 的不透明度。没有什么。 我尝试使用 JLabelJPanel 来显示图像,但没有效果。

请帮我解释一下。

这是相关代码。

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

内容 Pane :

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,并启用了窗口合成。 (我尝试禁用它,但随后一切变得更加奇怪)。 我希望它能在 Java 7 上运行,我不关心 6。

这是我的程序执行此操作的两个屏幕截图: Very wrong

将 ContentPane 涂成红色。

A little less wrong but still...

ContentPane 只是一个带有 setOpaque(false) 的普通 JPanel。 (我们为什么要涂成红色?)

最佳答案

实际上只需要做两件事

  1. setOpaque(false) 用于带有图像的面板。
  2. setBackground(new Color(0, 0, 0, 0)) 框架,最后一个 0 是 alpha

奖励:为了让事情变得有趣,我添加了一个 MouseMotionListener,这样你仍然可以移动它:)

enter image description here

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("/image/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 作为内容 Pane 。不知道这是做什么用的?

关于java - JFrame 自定义透明背景出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22329141/

相关文章:

java - View 类监听并响应自己的组件是否是一种不好的形式

JDialog 关闭后 Java JComponent 不重新绘制

Java 数组与泛型

java - java包名为什么要小写?

java - HSSFWorkbook - 使用不同值的单独列写入 Excel 数据

java - 以百分比设置按钮的大小

java - 将 Swing JList 绑定(bind)到数组中

Java世界风: how to access AnalyticSurface on DragEvent

Java Swing : how to create assist functionality to teach user how to use the software?

java - 1 个 JFrame 中的多个 JPanel 在调用时显示