【问题标题】:Set Transparent Color for the Whole JPanel为整个 JPanel 设置透明颜色
【发布时间】:2016-02-25 07:31:21
【问题描述】:

我有一个带有 JLabel 的 JPanel,它拥有一个图标图片。 如何在整个JPanel(包括JLabel Icon)的顶部设置透明的红色? 我为面板设置了透明背景色,但我希望包括图片在内的整个面板都获得这种透明颜色。类似于 JPanel 顶部的透明彩色玻璃

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class TransparentJLabel {
    private static final String IMAGE_PATH = "http://duke.kenai.com/Oracle/OracleStratSmall.png";

    private static void createAndShowUI() {
        JPanel panel = new JPanel();
        panel.setBackground(Color.pink);

        URL imageUrl;
        try {
            imageUrl = new URL(IMAGE_PATH);
            BufferedImage image = ImageIO.read(imageUrl);
            ImageIcon icon = new ImageIcon(image);
            JLabel label = new JLabel(icon);
            panel.add(label);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


        JFrame frame = new JFrame("TransparentJLabel");
        frame.getContentPane().add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}

【问题讨论】:

  • Swing 组件要么完全透明,要么完全不透明。您可以通过使组件完全透明并覆盖它的 paintComponent 方法并用您想要的任何颜色填充组件区域来作弊
  • 在这种情况下进行叠加要复杂得多。您可以考虑使用 JLayer/JXLayer。否则,您可以考虑使用 Overlay 布局管理器

标签: java swing jpanel awt transparent


【解决方案1】:

如果您只需要一个覆盖整个contentPane 的分层面板,一个简单的glassPane 就可以了(覆盖它的paintComponent(...) 方法)。例如:

JPanel glassPane = new JPanel() {
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setColor(new Color(0, 100, 0, 100));
        g2.fillRect(0, 0, getWidth(), getHeight());
        g2.dispose();
    }
};
glassPane.setOpaque(false);

frame.setGlassPane(glassPane);
frame.getGlassPane().setVisible(true);

但是,如果您只想要一个分层面板一个 JPanel,我会使用JLayer 结合LayerUI,正如MadProgrammer 已经提到的那样。您将需要一个自定义的 LayerUI 来覆盖 paint(Graphics g, JComponent c) 方法。我知道这听起来很危险,但老实说,我不知道其他方法......

我在下面提供了一个示例,这是输出:

如您所见,panel1(或更准确地说,JLayer)有点透明(RGBA = "0, 100, 0, 100"),panel2 是正常的。

代码:

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.*;
import javax.swing.plaf.LayerUI;

public class Example {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Example();
            }
        });
    }

    public Example() {
        JFrame frame = new JFrame("Example");

        JPanel panel1 = new JPanel();
        panel1.add(new JButton("Panel 1"));
        MyLayerUI layerUI = new MyLayerUI();
        JLayer<JPanel> panel1Layer = new JLayer<JPanel>(panel1, layerUI);
        panel1.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                if (layerUI.hasOverlay()) {
                    layerUI.setOverlay(false);
                } else {
                    layerUI.setOverlay(true);
                }
                panel1Layer.repaint();
            }
        });

        JPanel panel2 = new JPanel();
        panel2.add(new JButton("Panel 2"));

        JPanel contentPane = new JPanel(new GridLayout(2, 1));
        contentPane.add(panel1Layer);
        contentPane.add(panel2);

        frame.setContentPane(contentPane);

        frame.setSize(300, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

}

class MyLayerUI extends LayerUI<JPanel> {
    private boolean overlay = true;

    @Override
    public void paint(Graphics g, JComponent c) {
        super.paint(g, c);
        if (hasOverlay()) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setColor(new Color(0, 100, 0, 100));
            g2.fillRect(0, 0, c.getWidth(), c.getHeight());
            g2.dispose();
        }
    }

    public boolean hasOverlay() {
        return overlay;
    }

    public void setOverlay(boolean overlay) {
        this.overlay = overlay;
    }
}

【讨论】:

  • 能否请您提及如何在点击时删除 panel1Layer ?你打算将默认参数传递给paint方法还是用新的JPanel替换panel1Layer UI?
  • @Mehdi 是的,我认为指示是否应该绘制绿色区域的布尔值是最好的解决方案 - 我更新了代码。
  • @Mehdi 等等...您的意思是删除整个panel1Layer,包括按钮?如果这就是您的意思,请查看CardLayout
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 2011-08-06
  • 2011-02-11
  • 1970-01-01
相关资源
最近更新 更多