Java Swing将透明性应用于透明JPanel上的组件
我正在努力创建一个支持透明性的JPanel
,并且遇到了一个问题,我不确定如何将相同级别的透明性应用于添加到此面板的所有Component
。到目前为止,我的代码是:
package de.uebertreiberman.project.swing;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class JTransparancyPanel extends JPanel {
float opacity = 1.0f;
/**Constructor for JTransparentPanel
*/
public JTransparancyPanel()
{
super();
this.setOpaque(false);
}
/**Getter for opacity value of panel
*
* @return float containing opacity value of frame (0-1)
*/
public float getOpacity()
{
return opacity;
}
/**Setter for opacity value of panel
*
* @param value as float for opacity of frame (0-1)
*/
public void setOpacity(float value)
{
opacity = value;
repaint();
}
/**Converts opacity value (0-1) to opacity color (0-255)
*
* @param opacity as float opacity value (0-1)
* @return integer containing converted opacity value (0-255)
*/
public static int getOpacityColor(float opacity)
{
return (int)(opacity * 255);
}
/**Converts opacity color (0-255) to opacity value (0-1)
*
* @param opacity as integer value (0-255)
* @return float containing converted opacity value (0-1)
*/
public static float getOpacityValue(int opacity)
{
//Returns more or less the correct, capped value
//Just ignore it, it works, leave it :D
return capFloat((3.9216f*opacity)/1000f, 0.0f, 1.0f);
}
/**Returns float capped between minimum and maximum value
*
* @param value as original value
* @param min as minimum cap value
* @param max as maximum cap value
* @return float containing capped value
*/
public static float capFloat(float value, float min, float max)
{
if(value < min) value = min;
else if(value > max) value = max;
return value;
}
/**Merges color and opacity to new color
*
* @param bg as color for old color, only RGB will be used from that
* @return color with RGB from bg and A from opacity of frame
*/
Color getTransparencyColor(Color bg)
{
return new Color(getOpacityValue(bg.getRed()), getOpacityValue(bg.getGreen()), getOpacityValue(bg.getBlue()), opacity);
}
@Override
public void paintComponent(Graphics g)
{
//Draw transparent background before painting other Components
g.setColor(getTransparencyColor(getBackground()));
Rectangle r = g.getClipBounds();
g.fillRect(r.x, r.y, r.width, r.height);
//Paint other components
super.paintComponent(g);
}
}
最重要的部分基本上是在最后,我对paintComponent(Graphics g)
方法进行了介绍
我只是取backgroundcolor
,对它应用透明度并设置它
现在我想让这个面板的所有子组件也变得透明,我不太确定这样做最有效的方法是什么
你有什么建议
# 1 楼答案
我找到了一个解决方案——基本上就是我在评论中提到的:面板并没有真正画在屏幕上。取而代之的是,它被绘制成一个图像,并且这个图像被绘制成适当的
AlphaComposite
(滑块可用于设置面板的不透明度)
尽管这个解决方案简单、通用,并且基本上可以处理所有子组件,但有一点我不喜欢:需要调整
RepaintManager
。为了确保应用了面板的不透明度(并且子组件不是独立绘制的,并且是完全不透明度的),重绘管理器必须在重绘子组件时触发整个组件的重绘。我认为应该有没有这种解决方法的解决方案(例如,这可能是在面板上覆盖getGaphics
可能是合适的罕见情况之一),但没有效果。也许通常的嫌疑犯(camickr、气垫船等)会找到更优雅、简洁的解决方案在此之前,以下是作为MCVE的代码: