1

我对 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 的绘画机制。)

4

2 回答 2

4

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

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

  • paintComponent
  • paintBorder
  • paintChildren

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

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

在此处输入图像描述

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

我想你可能会发现...

有用;)

于 2013-01-07T23:50:55.873 回答
1

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

于 2013-01-07T18:24:32.777 回答