如何在JPanel中制作半透明的内容?

时间:2013-01-07 18:15:30

标签: java swing graphics awt

我对JPanel中组件的显示感到困惑。

假设我创建了一个半透明度为0.8f的自定义JPanel,如下所示: -

JPanel panel=new JPanel(){
        @Override
        public void paint(Graphics g)
        {
            super.paint(g);
            BufferedImage img=(BufferedImage)createImage(getWidth(),getHeight());
            Graphics2D g2=(Graphics2D) g.create();
            g2.setComposite(AlphaComposite.SrcOver.derive(0.8f));
            g2.drawImage(img,0,0,null);
        }
        @Override
        public Dimension getPreferredSize()
        {
            return new Dimension(300,300);
        }
    };

现在我将其设置为框架的contentPane。

frame.setContentPane(panel);

现在我添加一些按钮。

    frame.add(new JButton("Click Here"));
    frame.add(new JButton("Click Here"));
    frame.add(new JButton("Click Here"));
    frame.add(new JButton("Click Here"));

1)然后在输出中为什么我得到半透明按钮?由于JPanel是单层的,当我覆盖其paint方法然后添加按钮时,我首先绘制了半透明图像,按钮不能是半透明的他们应该过来。

2)同样在这4个按钮中只有2个是半透明的。为什么会有这样的偏见?

3)如果我在添加这4个按钮之前还添加了一个表,那么一切都变得半透明。为什么?

Object[] names = new Object[] {
             "Title", "Artist", "Album"
         };
         String[][] data = new String[][] {
             { "Los Angeles", "Sugarcult", "Lights Out" },
             { "Do It Alone", "Sugarcult", "Lights Out" },
             { "Made a Mistake", "Sugarcult", "Lights Out" },
             { "Kiss You Better", "Maximo Park", "A Certain Trigger" },
             { "All Over the Shop", "Maximo Park", "A Certain Trigger" },
             { "Going Missing", "Maximo Park", "A Certain Trigger" }
         };
         JTable table = new JTable(data, names);
         frame.add(table); 

4)如果我将paintComponent(Graphics g)用于JPanel,那么无论是否添加表格,或者添加了多少个按钮,都没有什么是半透明的。为什么?

(我在询问应用程序运行时的立即输出。我知道当鼠标滚过这些按钮或者如果单击表中的任何行时它将变为不透明,这是由于Swing的绘制机制。)

2 个答案:

答案 0 :(得分:4)

  

1)然后在输出中为什么我会得到半透明按钮?由于JPanel单身   分层,当我覆盖它时,我首先绘制了半透明图像   添加了paint方法然后按钮,按钮一定不能   半透明,因为他们应该过来。

实际上,你在按钮上绘制了半透明效果。 paint来电

  • paintComponent
  • paintBorder
  • paintChildren

然后你在已经画过的画面(孩子们)的顶部画了半透明效果。添加组件时没有任何区别,Swing将在多种情况下绘制组件,第一次是在组件首次实现时(在屏幕上可见)并响应脏区域(和批次)的更改其他)...不要欺骗自己,你无法控制自己...

将绘制过程视为分层方法。首先你绘制背景,然后你画中间地面,然后最后,前面的地面,然后你去了,泼了...

enter image description here

public class TestTranslucentControls {

    public static void main(String[] args) {
        new TestTranslucentControls();
    }

    public TestTranslucentControls() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage background;

        public TestPane() {
            setLayout(new GridBagLayout());
            try {
                background = ImageIO.read(new File("C:/Users/shane/Dropbox/MegaTokyo/poster.jpg"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            add(new JButton("1"));
            add(new JButton("2"));
            add(new JButton("3"));
            add(new JButton("4"));
            add(new JButton("5"));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setComposite(AlphaComposite.SrcOver.derive(0.25f));
                int x = (getWidth() - background.getWidth()) / 2;
                int y = (getHeight() - background.getHeight()) / 2;
                g2.drawImage(background, x, y, this);
                g2.dispose();
            }
        }

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

我想你可能会发现......

有用;)

答案 1 :(得分:1)

通常,您要覆盖paintComponent()而不是paint()。这可能是导致透明度问题的原因。其次,您可能想要更改布局。默认情况下,面板使用FlowLayout。您可能希望使用BorderLayout或GridBagLayout或两者的混合。