Nis*_*s36 7 java swing transparency paintcomponent
我一直在尝试为我正在开发的小游戏实现基本文本泡泡.不想过于花哨,我开始使用一个基本的圆角矩形,边框包含一些文字:

然后,我决定文本气泡应该在预设时间后淡出.这就是我偶然发现问题的地方:当我试图在测试窗口中显示气泡时,一切正常,但是当我在游戏中显示它们时,当气泡消失时会出现失真.我测试了一些,调试了,发现两种情况之间的唯一区别是在测试窗口我使用paintComponent方法的Graphics绘制了气泡,而在游戏中我使用BufferedImages来模拟图层并使用来自image.createGraphics的图形.然后我可以成功复制错误:

在这里,您可以看到当左边的气泡褪色时,与褪色前相比,它的圆角会改变形状,而右边圆角上的气泡不会改变.实际上,左边的气泡是在BufferedImage上绘制的,然后在面板上绘制,而右边的气泡直接在面板上绘制.
我已经隔离了重现问题所需的代码:
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(400, 400);
JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics graphics = image.createGraphics();
paintExampleBubble(graphics, 50, 50);
g.drawImage(image, 0, 0, this);
paintExampleBubble(g, 250, 50);
}
};
frame.getContentPane().add(panel);
frame.setVisible(true);
}
private static final Color background = new Color(1f, 1f, 1f, 0.5f);
private static final Color foreground = new Color(0f, 0f, 0f, 0.5f);
private static final int borderRadius = 16;
private static final int width = 100;
private static final int height = 50;
private static void paintExampleBubble(Graphics g, int x, int y) {
g.setColor(background);
g.fillRoundRect(x, y, width, height, borderRadius, borderRadius);
g.setColor(foreground);
g.drawRoundRect(x, y, width, height, borderRadius, borderRadius);
}
Run Code Online (Sandbox Code Playgroud)
以下是上述代码生成的结果:

无论如何,这表明绘制到BufferedImage是导致问题的原因,但是现在不能放弃BufferedImages.
我试图调试代码以查看可能导致这种差异的原因,并且只能注意到图形对象在涉及透明度时使用不同的组件进行绘制,但这无助于我解决我的问题,即使有可能迫使图形做我想要的,我宁愿避免黑客攻击,如果可能的话.
有没有人知道解决这个问题的相对简单有效的方法,或解决它?
无论如何,感谢花时间阅读这个:)
PS:因为这是我第一次提出问题,我可能错过了一些东西,所以请随时告诉我是否是这种情况!非常感谢.
编辑:正如我在评论中所说,游戏是基于像素艺术,因此我宁愿不使用抗锯齿,但保持圆角矩形的基本像素化外观.
在这里,您可以看到,当左侧的气泡消失时,其圆角与消失之前相比会改变形状,而右侧的气泡的圆角没有变化。事实上,左边的气泡绘制在 BufferedImage 上,然后绘制在面板上,而右边的气泡则直接绘制在面板上。
与其每次使用不同的 alpha 值重新绘制图像,不如创建一次并使用AlphaComposite来管理透明度。
下面是对您的示例的改编,具有三个“气泡”:最左侧是每次更改前景色时绘制图像,右侧两个使用AlphaComposite(中间使用创建过一次的图像,最右侧JPanel直接使用图形)。
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(600, 200);
final BufferedImage image = new BufferedImage(600, 200, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
paintExampleBubble(graphics, 250, 50, foreground);
graphics.dispose();
final JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
final BufferedImage i2 = new BufferedImage(600, 200, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = i2.createGraphics();
paintExampleBubble(graphics, 50, 50, alphaForeground);
graphics.dispose();
g.drawImage(i2, 0, 0, this);
//use Alpha Composite for transparency
Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER , alpha );
g2d.setComposite(comp);
g2d.drawImage(image, 0, 0, this);
paintExampleBubble(g2d, 450, 50, foreground);
}
};
javax.swing.Timer timer = new javax.swing.Timer(100, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
alpha -= 0.05;
if ( alpha < 0 ){
alpha = 1.0f;
}
alphaForeground = new Color(0f, 0f, 0f, alpha);
panel.repaint();
}
});
timer.start();
frame.getContentPane().add(panel);
frame.setVisible(true);
}
private static float alpha = 1.0f;
private static final Color background = new Color(1f, 1f, 1f, 1f);
private static final Color foreground = new Color(0f, 0f, 0f, 1f);
private static Color alphaForeground = new Color(0f, 0f, 0f, alpha);
private static final int borderRadius = 16;
private static final int width = 100;
private static final int height = 50;
private static void paintExampleBubble(Graphics g, int x, int y, Color color) {
g.setColor(background);
g.fillRoundRect(x, y, width, height, borderRadius, borderRadius);
g.setColor(color);
g.drawRoundRect(x, y, width, height, borderRadius, borderRadius);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的系统上,我在最左侧看到失真(使用前景色管理透明度),但在 AlphaComposite 透明度下却没有看到失真
| 归档时间: |
|
| 查看次数: |
452 次 |
| 最近记录: |