简体   繁体   English

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

[英]2 Smooth Round Corners of Rectangle in java with Red background

How can I create a rectangle with only 2 corners with Smooth Roundness on left side in java?如何在 java 的左侧创建一个只有 2 个角且具有平滑圆度的矩形?

Means a rectangle with top-left and bottom-left round and smooth corners with background filled with red color in java?表示在 java 中具有左上角和左下角圆角和平滑角的矩形,背景填充为红色?

I searched SO and googled but could not find 2 corners round with smooth.我搜索了 SO 并用谷歌搜索,但找不到光滑的 2 个圆角。

Just create a rounded rectangle similar to this:只需创建一个与此类似的圆角矩形:

RoundRectangle2D roundedRectangle = new RoundRectangle2D.Float(10, 10, 240, 160, 10, 10);

And then draw a normal rectangle from the midpoint, to a desired point to the right.然后从中点画一个正常的矩形,到右边的所需点。

Example diagram:示例图:

在此处输入图像描述

Note: Make sure you have no border.注意:确保没有边框。 I've drawn them in for illustrative effect.为了说明效果,我把它们画了出来。

Code:代码:

     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 does not implement a RoundedRectangle2D that does this. Swing 没有实现这样做的 RoundedRectangle2D。 But you can create one.但是你可以创建一个。

While the accepted answer works, it is also the 'lazy' solution.虽然公认的答案有效,但它也是“懒惰”的解决方案。 No offense.没有冒犯的意思。

Here is working code that creates a rectangular shape where the cornerFlags parameter can be used to specify which corners should be rounded.这是创建矩形的工作代码,其中cornerFlags参数可用于指定哪些角应该被圆角。

Usage: Replace RoundedRectangle2D.Double with ModifiedRoundRect in your code.用法:在代码中将RoundedRectangle2D.Double替换为ModifiedRoundRect

To allow only the top-left and bottom-left corners to be rounded, set cornerFlags = 3 .要仅允许对左上角和左下角进行圆角处理,请设置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