繁体   English   中英

java 中矩形的 2 个平滑圆角,红色背景

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM