为啥此计时器中的 alpha 在此 Java Swing 面板中绘制在其自身之上?

Posted

技术标签:

【中文标题】为啥此计时器中的 alpha 在此 Java Swing 面板中绘制在其自身之上?【英文标题】:Why does the alpha in this timer draw on top of itself in this Java Swing Panel?为什么此计时器中的 alpha 在此 Java Swing 面板中绘制在其自身之上? 【发布时间】:2020-12-01 09:34:09 【问题描述】:
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.Timer;

    public class Main 
        
        
        public static void main(String[] args) 
            JFrame frame = new JFrame();
            frame.setLayout(new FlowLayout());
            frame.setSize(new Dimension(100, 100));
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            TestPanel panel = new TestPanel();
            panel.setPreferredSize(new Dimension(50,50));
            frame.add(panel);
            frame.setVisible(true);
        
        
        static class TestPanel extends JPanel implements ActionListener
            
            private static final long serialVersionUID = 8518959671689548069L;
            
            public TestPanel() 
                super();
                Timer t = new Timer(1000, this);
                t.setRepeats(true);
                t.start();
            
            
            int opacity = 10;
            @Override
            public void actionPerformed(ActionEvent e) 
                if(opacity >= 250) 
                    opacity = 0;
                
                else 
                    this.setBackground(new Color(255, 212, 100, opacity));
                    this.repaint();
                    opacity+=10;
                    System.out.println("opacity is " + opacity);
                
            
            
        
    

alpha 变化的速度比它应该的要快。达到某一点后,不透明度下降,而控制台中打印的不透明度小于 250。调整窗口大小“重置”它,使 alpha 正确。

如何让它真正正确地绘制 alpha?

【问题讨论】:

【参考方案1】:
this.setBackground(new Color(255, 212, 100, opacity));

Swing 不支持透明背景。

Swing 期望组件是:

    不透明 - 这意味着组件将在进行自定义绘制之前先使用不透明颜色重新绘制整个背景,或者 完全透明 - 在这种情况下,Swing 将首先绘制第一个不透明父组件的背景,然后再进行自定义绘制。

setOpaque(...) 方法用于控制组件的 opaque 属性。

在任何一种情况下,这都可以确保移除任何绘画工件,并且可以正确完成自定义绘画。

如果你想使用透明,那么你需要自己做自定义绘画,以确保背景被清除。

面板的自定义绘画将是:

JPanel panel = new JPanel()

    protected void paintComponent(Graphics g)
    
        g.setColor( getBackground() );
        g.fillRect(0, 0, getWidth(), getHeight());
        super.paintComponent(g);
    
;
panel.setOpaque(false); // background of parent will be painted first

每个使用透明度的组件都需要类似的代码。

或者,您可以查看Background With Transparency 的自定义类,该类可用于为您完成上述工作的任何组件。

【讨论】:

以上是关于为啥此计时器中的 alpha 在此 Java Swing 面板中绘制在其自身之上?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 FireFox 会冻结我在此登录表单中的输入?

Java多线程 定时器

为啥 scanf() 在此代码中导致无限循环?

为啥我在此代码的循环中出现错误?

当我在此页面中声明方法时,为啥此代码会出现“找不到符号”错误?

为啥 MongoDB 填充方法在此应用程序中失败?