如何设置JPanel的透明背景?

Posted

技术标签:

【中文标题】如何设置JPanel的透明背景?【英文标题】:How to set a transparent background of JPanel? 【发布时间】:2011-02-02 11:09:59 【问题描述】:

JPanels 背景可以设置为透明吗?

我的框架有两个JPanels:

图像面板功能面板

Feature PanelImage Panel 重叠。 图像面板 作为背景工作,它从远程 URL 加载图像。

功能面板上我想绘制形状。由于 Feature Panel 的 背景颜色,现在无法看到 Image Panel

我需要使 Feature Panel 背景透明,同时仍然绘制其形状,并且我希望 Image Panel 可见(因为它正在执行图像的平铺和缓存功能) .

我使用了两个JPanel,因为我需要将图像和形状图分开。

有没有办法让重叠的 Jpanel 具有透明背景?

【问题讨论】:

JPanel在加载透明PNG图片时,设置JPanel.setOpaque(false);会使用图片透明方式,否则显示不透明图片。 【参考方案1】:

在上面的JPanel 上调用setOpaque(false) 应该可以工作。

从您的评论看来,Swing 绘画可能在某处损坏 -

首先 - 您可能想在您覆盖 paint() 的任何组件中覆盖 paintComponent() 而不是 paint()

第二 - 当你覆盖 paintComponent() 时,你首先要调用 super.paintComponent() 来执行所有默认的 Swing 绘制工作(其中尊重 setOpaque() 是其中之一)。

例子-

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class TwoPanels 
    public static void main(String[] args) 

        JPanel p = new JPanel();
        // setting layout to null so we can make panels overlap
        p.setLayout(null);

        CirclePanel topPanel = new CirclePanel();
        // drawing should be in blue
        topPanel.setForeground(Color.blue);
        // background should be black, except it's not opaque, so 
        // background will not be drawn
        topPanel.setBackground(Color.black);
        // set opaque to false - background not drawn
        topPanel.setOpaque(false);
        topPanel.setBounds(50, 50, 100, 100);
        // add topPanel - components paint in order added, 
        // so add topPanel first
        p.add(topPanel);

        CirclePanel bottomPanel = new CirclePanel();
        // drawing in green
        bottomPanel.setForeground(Color.green);
        // background in cyan
        bottomPanel.setBackground(Color.cyan);
        // and it will show this time, because opaque is true
        bottomPanel.setOpaque(true);
        bottomPanel.setBounds(30, 30, 100, 100);
        // add bottomPanel last...
        p.add(bottomPanel);

        // frame handling code...
        JFrame f = new JFrame("Two Panels");
        f.setContentPane(p);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(300, 300);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    

    // Panel with a circle drawn on it.
    private static class CirclePanel extends JPanel 

        // This is Swing, so override paint*Component* - not paint
        protected void paintComponent(Graphics g) 
            // call super.paintComponent to get default Swing 
            // painting behavior (opaque honored, etc.)
            super.paintComponent(g);
            int x = 10;
            int y = 10;
            int width = getWidth() - 20;
            int height = getHeight() - 20;
            g.drawArc(x, y, width, height, 0, 360);
        
    

【讨论】:

我做了,但是不起作用,我应该在构造函数中调用这个函数还是在paint()方法中调用这个函数? @Imran - 在构造函数中还是在什么的paint() 方法中?面板本身?查看更新的答案... 好的,谢谢 Nate,这很有效。在调用 super.paint() 之前,我将 Opaque 设置为 false,然后在绘制我的形状之前,我将 Opaque 设置为 true。谢谢朋友 你不应该打开和关闭它...基本上所有setOpaque()句柄都是是否应该绘制“背景” - 你可以在面板上调用它之后你创建它,它会保持不变。如果您在该面板上有一个覆盖的paintComponent(),您可以在组件上进行绘制(并确保调用 super.paintComponent() 以便可以进行默认的 Swing 绘制)并且您绘制的任何内容都将被视为“前景”并显示无需致电setOpaque(true) 好吧,我想我说得太早了,现在问题倒过来了。当下方的 Jpanel 重绘时,重叠的 Jpanel 的内容会被擦除。它是某种循环赛。我在没有背景的情况下绘制了重叠的 Jpanel,但是当重叠的 jpanel 重绘重叠的 jpanel 时,它的内容就会丢失,嗯……现在是什么。【参考方案2】:

或者,考虑The Glass Pane,在文章How to Use Root Panes 中讨论。您可以在玻璃窗格的 paintComponent() 方法中绘制您的“功能”内容。

附录:使用GlassPaneDemo,我添加了一张图片:

//Set up the content pane, where the "main GUI" lives.
frame.add(changeButton, BorderLayout.SOUTH);
frame.add(new JLabel(new ImageIcon("img.jpg")), BorderLayout.CENTER);

并更改了玻璃窗格的paintComponent() 方法:

protected void paintComponent(Graphics g) 
    if (point != null) 
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setComposite(AlphaComposite.getInstance(
            AlphaComposite.SRC_OVER, 0.3f));
        g2d.setColor(Color.yellow);
        g2d.fillOval(point.x, point.y, 120, 60);
    

如 here 所述,Swing 组件必须遵守 opaque property;在这个变体中,ImageIcon 完全填充了框架默认布局的BorderLayout.CENTER

【讨论】:

如果没有 setOpaque() (如我的帖子中所述)工作,使用玻璃窗格将无法(正确)工作。 你只能有一个玻璃窗格。如果说您想移动 JFrame 甚至更好,例如周围的 JPanel,并且它持有一个侧面不规则的对象,您希望该部分清晰。然后您可以将其与下面的面板混合以具有重叠的对象。【参考方案3】:

在我的特殊情况下,这样做更容易:

 panel.setOpaque(true);
 panel.setBackground(new Color(0,0,0,0,)): // any color with alpha 0 (in this case the color is black

【讨论】:

那是无效的——如果 opaque 为 true,面板保证完全填充其背景(它没有透明背景) 你说的是真的,但是为了设计的预期目的,设置任何带有 alpha 0 的颜色都将失效,除了他没有指定他是否需要访问背景面板组件,据我了解,较低级别的面板只是设置背景图像。【参考方案4】:
(Feature Panel).setOpaque(false);

希望这会有所帮助。

【讨论】:

【参考方案5】:

要设置透明,您可以将面板的不透明设置为 false 之类的

   JPanel panel = new JPanel();
   panel.setOpaque(false);

但要使其具有透明感,请使用 color 属性的 alpha 属性,例如

   JPanel panel = new JPanel();
   panel.setBackground(new Color(0,0,0,125));

Color 的最后一个参数用于 alpha,alpha 值范围在 0 到 255 之间,其中 0 表示完全透明,255 表示完全不透明

【讨论】:

【参考方案6】:
 public void paintComponent (Graphics g)
     
((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.0f)); // draw transparent background
     super.paintComponent(g);
    ((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,1.0f)); // turn on opacity
    g.setColor(Color.RED);
    g.fillRect(20, 20, 500, 300);
      

我试过这样,但是很闪

【讨论】:

【参考方案7】:

正如Thrasgod 在他的回答中正确显示的那样,最好的方法是使用paintComponent,但如果情况是有一个半透明的JPanel(或任何其他组件,真的)并且内部有一些不透明的东西。您还必须覆盖 paintChildren 方法并将 alfa 值设置为 1。 就我而言,我像这样扩展了 JPanel:

public class TransparentJPanel extends JPanel 

private float panelAlfa;
private float childrenAlfa;

public TransparentJPanel(float panelAlfa, float childrenAlfa) 
    this.panelAlfa = panelAlfa;
    this.childrenAlfa = childrenAlfa;


@Override
public void paintComponent(Graphics g) 
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(getBackground());
    g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setComposite(AlphaComposite.getInstance(
            AlphaComposite.SRC_OVER, panelAlfa));
    super.paintComponent(g2d);



@Override
protected void paintChildren(Graphics g) 
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(getBackground());
    g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setComposite(AlphaComposite.getInstance(
            AlphaComposite.SRC_ATOP, childrenAlfa));
  
    super.paintChildren(g); 

 //getter and setter

在我的项目中,如果我只希望 Jpanel 透明,我只需要实例化 Jpanel jp = new TransparentJPanel(0.3f, 1.0f);。 您也可以使用g2d.fillRoundRectg2d.drawRoundRect 来弄乱 JPanel 形状,但这不在此问题的范围内。

【讨论】:

paintChildren 方法真的有效吗? 1.您传递的是 g,而不是 g2d 和 2.我遇到了 setComposite 的问题,然后将 g2d 传递给了paintChildren。它只是不起作用,而 g2d.translate(x,y) 完美地使孩子们用偏移量绘制。似乎复合材料不知何故丢失了,或者只是在 paintChildren 方法中被覆盖。

以上是关于如何设置JPanel的透明背景?的主要内容,如果未能解决你的问题,请参考以下文章

用Netbeans在JPanel上添加背景图片,求详细指导!

CSS中背景颜色透明度如何设置?

Vue设置背景色透明度字体不透明

如何动态设置activity背景透明度

word文档如何设置图片背景透明

netbeans6.9.1中,如何能设置一个图片作为JFrame窗体的背景?