Java bug?为什么要绘制矩形而不是椭圆?

时间:2012-12-24 01:43:18

标签: java swing scale java-2d

下面的代码绘制矩形和2个椭圆。

enter image description here

虽然应绘制3个椭圆。

我的操作系统是Windows 7教授64位

我的Java是1.6 x86,也是1.7 x64测试。

为什么?

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

            }
        });

    }

}

2 个答案:

答案 0 :(得分:2)

我复制/粘贴了您的代码,并绘制了您所写的2个省略号,我做的唯一更改是将MigLayout替换为null,手动设置框架和面板尺寸并删除frame.pack()调用:

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

enter image description here

<强>更新 可以使用Oracle JDK(java版本“1.8.0-ea”)而不是OpenJDK重现问题。得到钻石形状,正如另一个答案中所指出的,比例因子是形状退化的根本原因,但不知道这应该是合适的行为,因此,这些JRE中必定存在一个错误。 以下测试程序适用于两个JRE:

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

答案 1 :(得分:1)

在Eclipse 7中复制Java 7,Windows 7,删除布局管理器。

我的感觉是,这是由于小浮点值的高缩放和不准确性的结合,减少了生成的点数。

如果替换0.0363和0.0362之间的值,则渲染API会中断。它不再生成弧,而是生成正方形。

解决方法是停止将巨大的缩放与小尺寸物体结合起来。缩小并增大尺寸。