Я попытался использовать метод drawOval с одинаковой высотой и шириной, но по мере увеличения диаметра круг становится хуже выглядящим. Что я могу сделать, чтобы иметь приличный круг, независимо от его размера. Как реализовать сглаживание в java или какой-либо другой метод.
Как нарисовать привлекательный круг в Java
Ответ 1
Как выясняется, Java2D (который я предполагаю - это то, что вы используете) уже довольно хорош в этом! Здесь есть достойный учебник: http://www.javaworld.com/javaworld/jw-08-1998/jw-08-media.html
Важная строка:
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Ответ 2
вы можете установить подсказки рендеринга:
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Ответ 3
Две вещи, которые могут помочь:
- Используйте
Graphics2D.draw(Shape)
с экземпляромjava.awt.geom.Ellipse2D
вместоGraphics.drawOval
- Если результат все еще неудовлетворительный, попробуйте использовать
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
Ответ 4
Конечно, вы устанавливаете радиус того, что вам нужно:
@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);
}
Ответ 5
Неспособность рисовать "приличный круг" связана с очень старой ошибкой 6431487.
Превращение сглаживания не очень помогает - просто проверьте тип "круга", созданный drawOval() или drawShape (Eclipse), когда размер требуемого круга составляет 16 пикселей (все еще довольно распространенный размер значка), а сглаживание - на. Большие сглаженные круги будут выглядеть лучше, но они по-прежнему асимметричны, если кто-то захочет внимательно посмотреть на них.
Кажется, что для рисования "приличного вида круга" нужно вручную нарисовать его. Без сглаживания это будет средний алгоритм окружения (этот question имеет ответ с довольно java-кодом для него).
Ответ 6
Спасибо Олегу Эстехину за указание отчета об ошибке, потому что он объясняет, как это сделать.
Вот несколько небольших кругов до и после. Увеличено несколько раз, чтобы увидеть сетку пикселей.
Сходясь по строке, они немного перемещаются по субпиксельным суммам.
Первый столбец без подсказок рендеринга. Второй - только с антиалиасами. Третий - с антиалиасами и чистым режимом.
Обратите внимание, что только с подсказками для antialias, первые три круга одинаковы, а последние два одинаковы. Кажется, происходит какой-то дискретный переход. Вероятно, округление в какой-то момент.
Вот код. Это в 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_ON
, так и VALUE_STROKE_PURE
, чтобы получить правильные круги, нарисованные с точностью субпикселя.
Ответ 7
ИЗМЕНИТЬ: 06 сентября 2017 г.
Это алгоритм, изобретенный мной, чтобы нарисовать круг над целочисленной матрицей. Та же идея может быть использована для записи круга внутри BufferedImage. Если вы пытаетесь рисовать этот круг с помощью класса Graphics, это не ваше антивирусное ПО, которое вы ищете (если вы не хотите изменять каждое назначение цвета с помощью 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;
}
Я пробовал это много раз, проверяя вручную его правильность, поэтому я думаю, что это сработает. Я не делал проверку диапазона только для упрощения кода. Надеюсь, это поможет вам и всем желающим нарисовать круг по матрице (например, тех программистов, которые пытаются создать свои собственные видеоигры на чистом коде и должны управлять матрично-ориентированной карточкой игры для хранения объектов, лежащих на game-map [если вам нужна помощь по этому поводу, напишите мне]).