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

4
以下代码绘制了矩形和2个椭圆。但应该绘制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);

            }
        });

    }

}

1
为了更快地获得更好的帮助,请发布一个SSCCE - Andrew Thompson
  1. g2d.scale(10000, 10000); 为什么要进行如此巨大的缩放?
  2. new JPanel() { @Override public void paint(Graphics g) 应该改为 new JPanel() { @Override public void paintComponent(Graphics g)
  3. 该方法的第一行通常应该调用 super,例如 super.paintComponent(g)
- Andrew Thompson
@Andrew(1)对于测试(2,3)没有帮助。 - Dims
2个回答

2

我复制/粘贴了你的代码,它画出了你写的2个椭圆形,我唯一做的更改是用null替换了你的MigLayout,手动设置了框架和面板的尺寸,并删除了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);
    }
}

输入图像描述

更新: 在使用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. 该字符串所示,没有NullLayout类。2) 面板应返回首选大小,以便布局管理器具有要使用的尺寸。
- Andrew Thompson
抱歉,我的错,确实,我是想用null替换MigLayout,已在答案中进行了更正。 - higuaro
@h3nr1x,你用的是什么操作系统和Java版本? - Dims
我在1.6.0中使用这两个代码得到了相同的结果(一旦另一个被编译),并且在1.7.0_09中(只使用你的代码)也得到了相同的结果,即正方形而不是椭圆形。 - Andrew Thompson
我正在使用OpenJDK版本1.7.0_09的Linux系统。 - higuaro

1

在Java 7、Windows 7和Eclipse上进行复制,移除布局管理器。

我的感觉是由于高比例尺和小浮点值的不准确性相结合,减少了生成的点数。

如果您替换在0.0363和0.0362之间找到的值,则呈现API会中断。它不再生成弧,而是生成一个正方形。

解决方法是停止将巨大的缩放与微小的对象组合在一起。缩小并增加大小。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接