Why does the alpha in this timer draw on top of itself in this Java Swing Panel?

匆匆过客 提交于 2020-08-26 08:28:31

问题


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

The rate the alpha changes is faster than it should be. After it reaches a certain point, the opacity drops, while the the opacity printed in the console is less than 250. Resizing the window "resets" it, making the alpha correct.

How do I make it actually draw the alpha correctly?


回答1:


this.setBackground(new Color(255, 212, 100, opacity));

Swing does not support transparent backgrounds.

Swing expects a component to be either:

  1. opaque - which implies the component will repaint the entire background with an opaque color first before doing custom painting, or
  2. fully transparent - in which case Swing will first paint the background of the first opaque parent component before doing custom painting.

The setOpaque(...) method is used to control the opaque property of a component.

In either case this makes sure any painting artifacts are removed and custom painting can be done properly.

If you want to use tranparency, then you need to do custom painting yourself to make sure the background is cleared.

The custom painting for the panel would be:

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

Similar code would be required for every component that uses transparency.

Or, you can check out Background With Transparency for custom class that can be used on any component that will do the above work for you.



来源:https://stackoverflow.com/questions/63362910/why-does-the-alpha-in-this-timer-draw-on-top-of-itself-in-this-java-swing-panel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!