2009-07-07 34 views
22

我已經嘗試使用相同的高度和寬度相等的方法drawOval,但隨着直徑增加圓看起來變得更糟糕。無論大小如何,我都可以做一個體面的圈子。我將如何在java或其他方法中實現反鋸齒。如何繪製一個像樣的圓環在Java中

回答

37

事實證明,Java2D的(我假設是你正在使用的)已經很不錯了!有一個像樣的教程在這裏:http://www.javaworld.com/javaworld/jw-08-1998/jw-08-media.html

的重要行是:

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

你必須愛鏈接11歲,希望他們永遠不會死。 – 2009-07-07 22:39:03

27

您可以設置呈現提示:

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

兩件事情,可以幫助:

  1. 使用Graphics2D.draw(Shape)java.awt.geom.Ellipse2D代替Graphics.drawOval
  2. 一個實例。如果結果仍然不理想,嘗試使用Graphics2D.setRenderingHint啓用抗混疊功能

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

見約瑟夫的回答爲setRenderingHint

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

你還需要設置橢圓的位置,我認爲你想要g2d.draw而不是g2d.stroke – finnw 2009-07-07 20:14:40

3

無力畫一個「體面的尋找圈」是關係到很老的bug 6431487

打開抗鋸齒功能並沒有什麼幫助 - 只需在所需的圓大小爲16像素(仍然很常見的圖標大小)和抗鋸齒功能時檢查由drawOval()或drawShape(Eclipse)生成的「圓」打開。更大的抗鋸齒圈看起來會更好,但如果有人會仔細看待它們,它們仍然是不對稱的。

似乎要畫一個「像樣的圓圈」,必須手動繪製一個。沒有抗鋸齒,它將是中點圓算法(這個question有一個漂亮的java代碼的答案)。

-1

編輯:2017年9月6日

這是由我發明的畫在整數矩陣的一個圓的算法。同樣的想法可以用來在BufferedImage中寫一個圓圈。 如果您正在嘗試使用類Graphics繪製該圓,那麼這不是您要查找的answare(除非您希望使用g.drawLine(x,y,x + 1,y)修改每個顏色分配,但它可能會非常緩慢)。

protected boolean runOnCircumference(int[][] matrix, int x, int y, int ray, int color) { 
    boolean ret; 
    int[] rowUpper = null, rowInferior = null, rowCenterUpper = null, rowCenterInferior = null; 

    if (ret = ray > 0) { 
     if (ray == 1) { 
      matrix[y][x + 1] = color; 
      rowUpper = matrix[++y]; 
      rowUpper[x] = color; 
      rowUpper[x + 2] = color; 
      matrix[y][x] = color; 
     } else { 
      double rRay = ray + 0.5; 
      int r = 0, c = 0, ray2 = ray << 1, ray_1 = ray - 1, halfRay = (ray >> 1) + ray % 2, rInf, 
        ray1 = ray + 1, horizontalSymmetricOldC; 
      // draw cardinal points 

      rowUpper = matrix[ray + y]; 
      rowUpper[x] = color; 
      rowUpper[x + ray2] = color; 
      matrix[y][x + ray] = color; 
      matrix[ray2 + y][x + ray] = color; 

      horizontalSymmetricOldC = ray1; 
      rInf = ray2; 
      c = ray_1; 
      for (r = 0; r < halfRay; r++, rInf--) { 

       rowUpper = matrix[r + y]; 
       rowInferior = matrix[rInf + y]; 

       while (c > 0 && (Math.hypot(ray - c, (ray - r)) < rRay)) { 

        rowUpper[x + c] = color; 
        rowUpper[x + horizontalSymmetricOldC] = color; 
        rowInferior[x + c] = color; 
        rowInferior[x + horizontalSymmetricOldC] = color; 

        // get the row pointer to optimize 
        rowCenterUpper = matrix[c + y]; 
        rowCenterInferior = matrix[horizontalSymmetricOldC + y]; 
        // draw 
        rowCenterUpper[x + r] = color; 
        rowCenterUpper[x + rInf] = color; 
        rowCenterInferior[x + r] = color; 
        rowCenterInferior[x + rInf] = color; 
        horizontalSymmetricOldC++; 
        c--; 
       } 
      } // end r circle 
     } 
    } 
    return ret; 
} 

我試了很多次,手動驗證它的正確性,所以我認爲它會工作。我沒有進行任何範圍檢查,只是爲了簡化代碼。 我希望它能幫助你和每個人都希望在矩陣上畫一個圓圈(例如,那些試圖在純代碼上創建自己的視頻遊戲的程序員,並且需要管理一個矩陣導向的遊戲地圖來存儲躺在遊戲地圖[如果您需要幫助,請發郵件給我])。

3

感謝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得到適當的尋求與亞像素精度描畫圓。