I was writing a program with some custom rendering, and needed to render a rectangle with a border. I decided to simply call graphics2D.fillRect(), switch to the border color, and call graphics2D.drawRect(). However, even though I make these calls back to back with the same coordinates and sizes, fillRect() does not always fill in the entire area contained by drawRect when the color I'm drawing with is translucent (has alpha). Furthermore, the area painted by fillRect() is sometimes outside of the area contained by drawRect(). Why do these two methods draw things in different places when given different colors?
Here is an example to demonstrate the problem. Clicking the mouse in the window will switch between drawing the fill with alpha and without. Notice that there is a row of pixels at the bottom of the rectangle that is white when drawing with alpha, but that row of pixels is not there when drawing without alpha.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ColorWithAlpha extends JPanel {
private boolean hasAlpha = true;
private static final long serialVersionUID = 1L;
/**
* @param args
*/
public static void main(String[] args) {
// setup a basic frame with a ColorWithAlpha in it
JFrame frame = new JFrame();
JPanel panel = new ColorWithAlpha();
panel.setPreferredSize(new Dimension(500, 500));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.show();
}
public ColorWithAlpha() {
super();
setBackground(Color.WHITE);
this.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent arg0) {
// when the user clicks their mouse, toggle whether we are drawing a color with alhpa or without.
hasAlpha = !hasAlpha;
ColorWithAlpha.this.repaint();
}
@Override
public void mouseEntered(MouseEvent arg0) {}
@Override
public void mouseExited(MouseEvent arg0) {}
@Override
public void mousePressed(MouseEvent arg0) {}
@Override
public void mouseReleased(MouseEvent arg0) {}
});
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Color color = new Color(100, 100, 250);// this color doesnt have an alpha component
// some coordinates that demonstrate the bug. Not all combinations of x,y,width,height will show the bug
int x = -900;
int y = 1557;
int height = 503;
int width = 502;
if (hasAlpha) { // toggle between drawing with alpha and without
color = new Color(200, 100, 250, 100);
}
Graphics2D g2 = (Graphics2D) g;
// this is the transform I was using when I found the bug.
g2.setTransform(new AffineTransform(0.160642570281124, 0.0, 0.0, -0.160642570281124, 250.0, 488.0));
g2.setColor(color);
g2.fillRect(x, y, width, height);
g2.setColor(Color.DARK_GRAY);
g2.setStroke(new BasicStroke(8f));
g2.drawRect(x, y, width, height);
}
}