Java graphics2D fillRect does not work properly with semi-transparent colors
awt, graphics2d, java, java-2d, swing
Solution
Scrap that answer, I reread your question and copied your code and found what your talking about. The small white line is due to a round-off error in the painting. Very interesting little problem. Add this after creating your Graphics2D
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
Rendering hints tell the painting class how you want certain procedures to work. I have no idea why adding transparency to the color would make the roundoff different. I figure it must have to do with multiple rendering hints combining together like antialiasing.
Problem
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); } } ```