[英]2 Smooth Round Corners of Rectangle in java with Red background
如何在 java 的左侧创建一个只有 2 个角且具有平滑圆度的矩形?
表示在 java 中具有左上角和左下角圆角和平滑角的矩形,背景填充为红色?
我搜索了 SO 并用谷歌搜索,但找不到光滑的 2 个圆角。
只需创建一个与此类似的圆角矩形:
RoundRectangle2D roundedRectangle = new RoundRectangle2D.Float(10, 10, 240, 160, 10, 10);
然后从中点画一个正常的矩形,到右边的所需点。
示例图:
注意:确保没有边框。 为了说明效果,我把它们画了出来。
代码:
Graphics2D g2 = (Graphics2D) g;
RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON );
qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY );
g2.setRenderingHints( qualityHints );
g2.setPaint(Color.RED);
double x = 50;
double y = 50;
double w = x + 250;
double h = y + 100;
g2.fill(new RoundRectangle2D.Double(x, y, w, h, 50, 50));
g2.fill(new Rectangle2D.Double(x + 100,y,w,h));
Swing 没有实现这样做的 RoundedRectangle2D。 但是你可以创建一个。
虽然公认的答案有效,但它也是“懒惰”的解决方案。 没有冒犯的意思。
这是创建矩形的工作代码,其中cornerFlags
参数可用于指定哪些角应该被圆角。
用法:在代码中将RoundedRectangle2D.Double
替换为ModifiedRoundRect
。
要仅允许对左上角和左下角进行圆角处理,请设置cornerFlags = 3
。
package ui1.app.widgets;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.Arrays;
import java.util.NoSuchElementException;
public class ModifiedRoundRect extends RoundRectangle2D {
public double x;
public double y;
public double width;
public double height;
public double arcwidth;
public double archeight;
private int cornerFlags;
public ModifiedRoundRect(double x, double y, double w, double h, double arcw, double arch,
int cornerFlags) {
this.setRoundRect(x, y, w, h, arcw, arch);
this.cornerFlags = cornerFlags;
}
public double getX() {
return this.x;
}
public double getY() {
return this.y;
}
public double getWidth() {
return this.width;
}
public double getHeight() {
return this.height;
}
public double getArcWidth() {
return this.arcwidth;
}
public double getArcHeight() {
return this.archeight;
}
public int getCornerFlags() {
return cornerFlags;
}
public boolean isEmpty() {
return this.width <= 0.0D || this.height <= 0.0D;
}
public void setRoundRect(double x, double y, double w, double h, double arcw, double arch) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.arcwidth = arcw;
this.archeight = arch;
this.cornerFlags = 15;
}
public void setRoundRect(RoundRectangle2D rr) {
this.x = rr.getX();
this.y = rr.getY();
this.width = rr.getWidth();
this.height = rr.getHeight();
this.arcwidth = rr.getArcWidth();
this.archeight = rr.getArcHeight();
this.cornerFlags = 15;
}
public void setRoundRect(ModifiedRoundRect rr) {
this.x = rr.getX();
this.y = rr.getY();
this.width = rr.getWidth();
this.height = rr.getHeight();
this.arcwidth = rr.getArcWidth();
this.archeight = rr.getArcHeight();
this.cornerFlags = rr.getCornerFlags();
}
public Rectangle2D getBounds2D() {
return new java.awt.geom.Rectangle2D.Double(this.x, this.y, this.width, this.height);
}
@Override
public PathIterator getPathIterator(AffineTransform at) {
return new ModifiedRoundRectIterator(this, at, cornerFlags);
}
static class ModifiedRoundRectIterator implements PathIterator {
double x;
double y;
double w;
double h;
double aw;
double ah;
AffineTransform affine;
int index;
private static final double angle = 0.7853981633974483D;
private static final double a = 1.0D - Math.cos(0.7853981633974483D);
private static final double b = Math.tan(0.7853981633974483D);
private static final double c;
private static final double cv;
private static final double acv;
private double[][] curves;
private int[] types;
ModifiedRoundRectIterator(RoundRectangle2D rr, AffineTransform at, int cornerFlags) {
this.x = rr.getX();
this.y = rr.getY();
this.w = rr.getWidth();
this.h = rr.getHeight();
this.aw = Math.min(this.w, Math.abs(rr.getArcWidth()));
this.ah = Math.min(this.h, Math.abs(rr.getArcHeight()));
this.affine = at;
if (this.aw < 0.0D || this.ah < 0.0D) {
this.index = curves.length;
}
createCurves(cornerFlags);
}
void createCurves(int cornerFlags) {
// notes:
// - curves are drawn counter-clock-wise
// - a rectangle requires 4 segments + a start and close segment = 6
// - 4 rounded rectangles adds 4 segments = 10
boolean topLeft = (cornerFlags & 1) == 1;
boolean bottomLeft = (cornerFlags & 2) == 2;
boolean bottomRight = (cornerFlags & 4) == 4;
boolean topRight = (cornerFlags & 8) == 8;
int numberOfSegments =
6 + (int)Arrays.asList(topLeft, bottomLeft, bottomRight, topRight)
.stream()
.filter(flag -> flag)
.count();
types = new int[numberOfSegments];
curves = new double[numberOfSegments][];
int i = 0;
types[i] = PathIterator.SEG_MOVETO;
curves[i] = new double[] { 0.0D, 0.0D, 0.0D, topLeft ? 0.5D : 0D };
i++;
// line to bottom-left
types[i] = PathIterator.SEG_LINETO;
curves[i] = new double[] { 0.0D, 0.0D, 1.0D, bottomLeft ? -0.5D : 0D };
i++;
if (bottomLeft) {
// rounded corner at bottom left
types[i] = PathIterator.SEG_CUBICTO;
curves[i] =
new double[] { 0.0D, 0.0D, 1.0D, -acv, 0.0D, acv, 1.0D, 0.0D, 0.0D, 0.5D,
1.0D, 0.0D };
i++;
}
// line to bottom-right
types[i] = PathIterator.SEG_LINETO;
curves[i] = new double[] { 1.0D, bottomRight ? -0.5D : 0D, 1.0D, 0.0D };
i++;
if (bottomRight) {
// rounded corner at bottom right
types[i] = PathIterator.SEG_CUBICTO;
curves[i] =
new double[] { 1.0D, -acv, 1.0D, 0.0D, 1.0D, 0.0D, 1.0D, -acv, 1.0D, 0.0D,
1.0D, -0.5D };
i++;
}
// line to top right
types[i] = PathIterator.SEG_LINETO;
curves[i] = new double[] { 1.0D, 0.0D, 0.0D, topRight ? 0.5D : 0D };
i++;
if (topRight) {
// rounded corner at top right
types[i] = PathIterator.SEG_CUBICTO;
curves[i] =
new double[] { 1.0D, 0.0D, 0.0D, acv, 1.0D, -acv, 0.0D, 0.0D, 1.0D, -0.5D,
0.0D, 0.0D };
i++;
}
// line to top left
types[i] = PathIterator.SEG_LINETO;
curves[i] = new double[] { 0.0D, topLeft ? 0.5D : 0D, 0.0D, 0.0D };
i++;
if (topLeft) {
// rounded corner at top left
types[i] = PathIterator.SEG_CUBICTO;
curves[i] =
new double[] { 0.0D, acv, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, acv, 0.0D, 0.0D,
0.0D, 0.5D };
i++;
}
types[i] = PathIterator.SEG_CLOSE;
curves[i] = new double[0];
i++;
}
public int getWindingRule() {
return WIND_NON_ZERO;
}
public boolean isDone() {
return this.index >= curves.length;
}
public void next() {
++this.index;
}
public int currentSegment(float[] coords) {
if (this.isDone()) {
throw new NoSuchElementException("roundrect iterator out of bounds");
} else {
System.out.println("ModifiedRoundRectIterator segment: " + index);
double[] ctrls = curves[this.index];
int nc = 0;
for (int i = 0; i < ctrls.length; i += 4) {
coords[nc++] = (float)(this.x + ctrls[i + 0] * this.w + ctrls[i + 1] * this.aw);
coords[nc++] = (float)(this.y + ctrls[i + 2] * this.h + ctrls[i + 3] * this.ah);
}
if (this.affine != null) {
this.affine.transform(coords, 0, coords, 0, nc / 2);
}
return types[this.index];
}
}
public int currentSegment(double[] coords) {
if (this.isDone()) {
throw new NoSuchElementException("roundrect iterator out of bounds");
} else {
System.out.println("ModifiedRoundRectIterator segment: " + index);
double[] ctrls = curves[this.index];
int nc = 0;
for (int i = 0; i < ctrls.length; i += 4) {
coords[nc++] = this.x + ctrls[i + 0] * this.w + ctrls[i + 1] * this.aw;
coords[nc++] = this.y + ctrls[i + 2] * this.h + ctrls[i + 3] * this.ah;
}
if (this.affine != null) {
this.affine.transform(coords, 0, coords, 0, nc / 2);
}
return types[this.index];
}
}
static {
c = Math.sqrt(1.0D + b * b) - 1.0D + a;
cv = 1.3333333333333333D * a * b / c;
acv = (1.0D - cv) / 2.0D;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.