The alpha in this timer draw on top of itself in this Java Swing Panel.

huangapple go评论67阅读模式
英文:

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

问题

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 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?

英文:
    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

得分: 4

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

Swing 不支持半透明背景。

Swing 期望组件要么是:

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

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

无论哪种情况,这都可以确保删除任何绘制残留,从而可以正确进行自定义绘制。

如果您想要使用透明度,那么需要自己进行自定义绘制以确保清除背景。

面板的自定义绘制将如下所示:

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 With Transparency,其中提供了一个自定义类,可用于任何组件,以执行上述工作。

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

Swing does not support semi 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.

huangapple
  • 本文由 发表于 2020年8月12日 00:58:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/63362910.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定