Reputation: 51229
The code below draws rectangle and 2 ellipses.
While should draw 3 ellipses.
My OS is Windows 7 prof 64 bit
My Java is 1.6 x86 also 1.7 x64 tested.
Why?
package tests;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class AntialiacingScaleTester {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JPanel circlePanel = new JPanel() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.RED);
g2d.setStroke(new BasicStroke(1));
//g2d.drawOval(0, 0, 200, 200);
g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));
AffineTransform old = g2d.getTransform();
g2d.setColor(Color.GREEN);
g2d.scale(1000, 1000);
g2d.setStroke(new BasicStroke(0.001f));
g2d.draw(new Ellipse2D.Double(0, 0, 0.225, 0.225));
g2d.setColor(Color.BLUE);
g2d.scale(10, 10);
g2d.setStroke(new BasicStroke(0.001f));
g2d.draw(new Ellipse2D.Double(0, 0, 0.025, 0.025));
g2d.setTransform(old);
}
};
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setLayout(new MigLayout("fill"));
//frame.add(circlePanel, "w 300, h 300, grow");
//frame.add(circlePanel);
frame.setLayout(null);
circlePanel.setBounds(new Rectangle(0, 0, 300, 300));
frame.add(circlePanel);
frame.setBounds(0, 0, 350, 300);
//frame.pack();
frame.setVisible(true);
}
});
}
}
Upvotes: 4
Views: 841
Reputation: 16059
I copy/pasted your code and it drew the 2 ellipses you wrote about, the only change I made was to replace your MigLayout
by null
, set the frame and panel dimensions by hand and remove the frame.pack()
invocation:
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
JPanel circlePanel = new JPanel() {
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(1));
//g2d.drawOval(0, 0, 200, 200);
g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));
AffineTransform old = g2d.getTransform();
g2d.scale(10000, 10000);
g2d.setStroke(new BasicStroke(0.001f));
g2d.draw(new Ellipse2D.Double(0, 0, 0.025, 0.025));
g2d.setTransform(old);
}
};
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
circlePanel.setBounds(new Rectangle(0, 0, 300, 300));
frame.add(circlePanel);
frame.setBounds(0, 0, 350, 300);
//frame.pack();
frame.setVisible(true);
}
}
Update: Could reproduce the problem using the Oracle JDK (java version "1.8.0-ea") instead of the OpenJDK. Got the diamond shape, as pointed out in another answers, the scale factor is the root cause of the shape degenaration, don't know if that should be the appropiate behaviour though, so, there must be a bug in one these JRE's. The following test program works fine for both JRE's:
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
JPanel circlePanel = new JPanel() {
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(1));
//g2d.drawOval(0, 0, 200, 200);
g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));
AffineTransform old = g2d.getTransform();
g2d.scale(10, 10);
g2d.setStroke(new BasicStroke(1.0f));
g2d.draw(new Ellipse2D.Double(0, 0, 25.0, 25.0));
g2d.setTransform(old);
}
};
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
circlePanel.setBounds(new Rectangle(0, 0, 300, 300));
frame.add(circlePanel);
frame.setBounds(0, 0, 350, 300);
//frame.pack();
frame.setVisible(true);
}
}
Upvotes: 2
Reputation: 4157
Replicated on Java 7, Windows 7 in Eclipse, removing the Layout Manager.
My feeling is that it's due to the combination of the high scaling and inaccuracies at small floating point values, reducing the number of points generated.
If you substitute values you find between 0.0363 and 0.0362 the rendering API breaks. It no longer generates an Arc, but instead a square.
The work-around is to stop combining the huge scaling with tiny sized objects. Scale down and increase the size.
Upvotes: 1