如何在Java中绘制一个像样的圆圈

时间:2009-07-07 20:03:09

标签: java graphics antialiasing geometry

我尝试使用drawOval方法具有相同的高度和宽度,但随着直径的增加,圆圈变得更糟。无论大小如何,我能做些什么才能拥有体面的圆圈。我将如何在java或其他方法中实现消除锯齿。

7 个答案:

答案 0 :(得分:42)

事实证明,Java2D(我假设你正在使用的)已经相当不错了!这里有一个不错的教程:http://www.javaworld.com/javaworld/jw-08-1998/jw-08-media.html

重要的一点是:

graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                          RenderingHints.VALUE_ANTIALIAS_ON);

答案 1 :(得分:28)

您可以设置渲染提示:

Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    RenderingHints.VALUE_ANTIALIAS_ON);

答案 2 :(得分:12)

有两件事可能会有所帮助:

  1. Graphics2D.draw(Shape)与[{1}}实例一起使用,而不是java.awt.geom.Ellipse2D
  2. 如果结果仍不理想,请尝试使用Graphics.drawOval启用抗锯齿
  3. 实施例

    Graphics2D.setRenderingHint

    请参阅Josef的答案,了解public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; Shape theCircle = new Ellipse2D.Double(centerX - radius, centerY - radius, 2.0 * radius, 2.0 * radius); g2d.draw(theCircle); }

    的示例

答案 3 :(得分:6)

当然,您可以根据需要设置半径:

@Override
public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    Ellipse2D.Double hole = new Ellipse2D.Double();
    hole.width = 28;
    hole.height = 28;
    hole.x = 14;
    hole.y = 14;
    g2d.draw(hole);
}

答案 4 :(得分:4)

感谢Oleg Estekhin指出错误报告,因为它解释了如何做到这一点。

以下是前后的一些小圈子。放大几次以查看像素网格。

Circles before and after

连续下去,他们按子像素数量略微移动。

第一列没有渲染提示。第二个是仅使用抗锯齿。第三种是抗锯齿和纯模式。

请注意,仅使用抗锯齿提示,前三个圆圈是相同的,后两个圆圈也是相同的。似乎发生了一些离散的转变。可能在某个时候四舍五入。

这是代码。它在Jython中是为了便于阅读,但是它驱动下面的Java运行时库并且可以无损地移植到等效的Java源代码,效果完全相同。

from java.lang import *
from java.io import *
from java.awt import *
from java.awt.geom import *
from java.awt.image import *
from javax.imageio import *

bim = BufferedImage(30, 42, BufferedImage.TYPE_INT_ARGB)
g = bim.createGraphics()
g.fillRect(0, 0, 100, 100)
g.setColor(Color.BLACK)
for i in range(5):
    g.draw(Ellipse2D.Double(2+0.2*i, 2+8.2*i, 5, 5))

g.setRenderingHint( RenderingHints.  KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON)

for i in range(5):
    g.draw(Ellipse2D.Double(12+0.2*i, 2+8.2*i, 5, 5))

g.setRenderingHint( RenderingHints.  KEY_STROKE_CONTROL,
                    RenderingHints.VALUE_STROKE_PURE)

for i in range(5):
    g.draw(Ellipse2D.Double(22+0.2*i, 2+8.2*i, 5, 5))

#You'll probably want this too later on:
#g.setRenderingHint( RenderingHints.  KEY_INTERPOLATION,
#                    RenderingHints.VALUE_INTERPOLATION_BICUBIC)
#g.setRenderingHint( RenderingHints.  KEY_RENDERING, 
#                    RenderingHints.VALUE_RENDER_QUALITY)

ImageIO.write(bim, "PNG", File("test.png"))

摘要:您需要VALUE_ANTIALIAS_ONVALUE_STROKE_PURE来获得以亚像素精度绘制的正确圆圈。

答案 5 :(得分:3)

无法画出“体面的圆圈”与很老的错误6431487有关。

打开抗锯齿并没有多大帮助 - 只需检查drawOval()或drawShape(Eclipse)产生的“圆圈”类型,当所需的圆圈大小为16像素时(图标大小仍然很常见)并且抗锯齿是上。更大的抗锯齿圈看起来会更好,但如果有人愿意密切关注它们,它们仍然是不对称的。

似乎要绘制“体面的圆圈”,必须手动绘制一个。如果没有抗锯齿,它将是中点圆算法(这个question有一个很好的java代码答案)。

答案 6 :(得分:-1)

编辑:2017年9月6日

这是我发明的算法,用于在整数矩阵上绘制一个圆。可以使用相同的想法在BufferedImage中写一个圆圈。 如果你试图使用类Graphics绘制那个圆圈,这不是你正在寻找的answare(除非你希望用g.drawLine(x,y,x + 1,y)修改每个颜色分配,但它可以非常慢。)

var MyRadioButton = React.createClass({
  handleChange: function () {
    this.props.onChange(this.props.myValue)
  },
  render: function () {
    return (
      <input type="radio" onChange={this.handleChange}>{this.props.myValue}</input>
    )
  }
});


var MyApp = React.createClass({
  getInitialState: function () {
    return {
      selectedValue: ''
    }
  },
  changeValue: function (newValue) {
    this.setState({selectedValue: newValue })
  },
  render: function () {
    return (
      <div>
        <MyRadioButton onChange={this.changeValue} myValue="A" />
        <MyRadioButton onChange={this.changeValue} myValue="B" /><br></br>
      </div>
    )
  }
});

我尝试了很多次,手动验证它的正确性,所以我认为它会起作用。我没有进行任何范围检查只是为了简化代码。 我希望它会帮助你,每个人都希望在矩阵上绘制一个圆圈(例如,那些试图在纯代码上创建自己的视频游戏并需要管理面向矩阵的游戏地图以存储位于矩阵上的对象的程序员游戏地图[如果你需要帮助,请给我发电子邮件]。