如何将JFrame背景设置为透明,但保持JPanel或JLabel的不透明性?

8
根据任务要求,我们需要创建一个类似于 Picasa 的图片浏览器。中间是图片,周围是半透明的黑色背景,可以通过左/右按钮更改图片。
我能够显示一张图片,并将其设置为底板,将其设置为半透明边框,但是在添加边框后,图片也变得半透明了。我做错了什么?
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();   

JFrame f1 = new JFrame("ShowImage");
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f1.setSize(dim);

f1.setUndecorated(true);
f1.setOpacity(0.5f);
ShowImage panel = new ShowImage();
panel.setBackground(Color.black);

f1.setContentPane(panel); 
f1.setVisible(true);  

我尝试过

si.setOpaque();   
si.setBackground(Color.black);
si.setForeground(Color.red);

没有任何一个起作用

当我使用一个布尔值进行测试时

si.isDisplayable();
si.isVisible();
si.isShowing();

只有返回 true 的内容是可见的,其余的都是 false,这是否有任何影响因素?


“JLabel” 默认情况下应该是非不透明的,为什么你希望它变成不同?有任何特殊需求吗? - nIcE cOw
JLabel只是一种显示图片的方法,我认为这是最简单的方法。我想要实现的是透明背景(窗口)和不透明前景(由JLabel导入的图片)。但我已经以正确的方式导入了它,所以我怀疑Label不再必要。感谢你的努力。 - sabbibJAVA
"我尝试过" si.setOpaque(); "那将会是一个编译错误。为了更快地获得帮助,请发布一个SSCCE。" - Andrew Thompson
1个回答

21
问题是,JFrame 的默认布局管理器是 BorderLayout,这意味着您的 ShowImage 面板填充了整个框架区域(黑色)。我敢打赌,如果您将 ShowPane 的背景更改为红色,则它将完全填充为红色。

现在您可以查看 布局管理器的可视化指南 或更改您的 ShowPane 工作方式

更新

抱歉,我不熟悉 Java 7 中的新透明度 API(仍在使用 Java 6 hack ;))

Transparent Frame

你能为我确认一下这是你要寻找的效果吗? 红色正方形会是图像(黑色背景则是边框 - 注意,我只捕捉了边框)。
更新。

Image Preview

首先,你需要阅读Window.isOpaqueWindow.setBackground以了解此解决方案的工作原理。
接下来,不要使用Window.setOpacity,它无法实现你想要的效果。主要原因是透明度值被应用于父级和其子级(这让我感到困惑)。
因此,框架代码如下:
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Make sure where in the top left corner, please lookup how
// to find the screen insets ;)
setLocation(0, 0);
setSize(dim);
// Set undecorated
setUndecorated(true);
// Apply a transparent color to the background
// This is ALL important, without this, it won't work!
setBackground(new Color(0, 255, 0, 0));

// This is where we get sneaky, basically where going to 
// supply our own content pane that does some special painting
// for us
setContentPane(new ContentPane());
getContentPane().setBackground(Color.BLACK);
setLayout(new BorderLayout());

// Add out image pane...    
ShowImage panel = new ShowImage();
add(panel);

setVisible(true);

ContentPane。基本上,我们需要“欺骗”绘画引擎,让它认为是透明的(而不是不透明的),然后绘制我们自己的不透明度。

public class ContentPane extends JPanel {

    public ContentPane() {

        setOpaque(false);

    }

    @Override
    protected void paintComponent(Graphics g) {

        // Allow super to paint
        super.paintComponent(g);

        // Apply our own painting effect
        Graphics2D g2d = (Graphics2D) g.create();
        // 50% transparent Alpha
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));

        g2d.setColor(getBackground());
        g2d.fill(getBounds());

        g2d.dispose();

    }

}

抱歉之前的回答,但我希望这个可以弥补它 ;) 按键更新 这是我对它进行的修改。
ShowImage panel = new ShowImage();
panel.setBackground(Color.RED);

setContentPane(new ContentPane());
getContentPane().setBackground(Color.BLACK);
setLayout(new BorderLayout());
add(panel);

JPanel pnlButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
pnlButtons.setOpaque(false);
pnlButtons.add(new JButton("<<"));
pnlButtons.add(new JButton("<"));
pnlButtons.add(new JButton(">"));
pnlButtons.add(new JButton(">>"));

// Okay, in theory, getContentPane() is required, but better safe the sorry
getContentPane().add(pnlButtons, BorderLayout.SOUTH);

setVisible(true);

Sample with Buttons


等一下,我想我可能知道发生了什么,让我运行更多的测试,看看能否使其工作 ;) - MadProgrammer
你能验证一下我的更新是否正确吗?如果是的话,我会发布一些代码来说明如何使其工作。 - MadProgrammer
你在哪里工作,Java?还是高中生就是这么笨:P 我开玩笑的。谢谢,它像魔法一样奏效了,尽管程序进行到一半。我只是好奇,你是怎么看到我的问题的,还是你会四处浏览帮助别人,我非常感激你的帮助。我希望你能在我的未来问题中回答。再次感谢。 - sabbibJAVA
我需要进行的一个更正是,不再使用 getContentPane().setBackground(Color.BLACK); 而是使用 **getContentPane().setBackground(getBackground());**。 - George Z.
你可以使用Color.RED来将背景变成红色,或者使用任何你想要的颜色。这完全由你决定。 - MadProgrammer
显示剩余28条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接