Java graphics2D fillRect does not work properly with semi-transparent colors

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);

}
}

Answers


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.


Need Your Help

MySQL subquery with group by in left join - optimisation

mysql optimization group-by subquery left-join

MySQL seems to be unable to optimise a select with a GROUP BY subquery and ends up in long execution times. There must be a known optimisation for such common scenario.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.