使用Graphics2D绘制菱形、五角星等任意图形

本文详细介绍了Java中GeneralPath类的使用,包括构造函数、绘制线段的方法如moveTo、lineTo等,并通过实例展示了如何绘制不规则形状、闭合形状、菱形和复杂的五角星。五角星的绘制涉及到10个坐标点的动态计算,作者提供了计算方法并鼓励读者点赞和关注。
摘要由CSDN通过智能技术生成

在上篇文章中我们已经通过Graphics2D绘制了大部分的形状,但是在现实需求中,可能需要我们绘制各式各样的形状,这个时候我们就需要用到GeneralPath这个类。

上篇文章传送门:https://blog.csdn.net/u011837804/article/details/129504353

本篇文章我们讲解GeneralPath类的详细使用方法,调用方法说明,以及通过绘制绘制不规则形状、绘制不规则形状并且自动闭合、绘制菱形、绘制五角星实例代码详解绘制任意形状。

其中绘制五角星是真的复杂,因为五角星有10个坐标点需要动态计算,但是考虑到自己国家的国徽必须绘制出来,经过几天的学习研究,总于搞定,吐血分享出来,全网几乎找不到Java绘制的参考点,如果觉得有用的朋友一定点赞加关注,感谢。

GeneralPath构造函数说明

    /**
     * Constructs a new {@code GeneralPath} object with the specified
     * winding rule and the specified initial capacity to store path
     * coordinates.
     * This number is an initial guess as to how many path segments
     * will be added to the path, but the storage is expanded as
     * needed to store whatever path segments are added.
     *
     * @param rule the winding rule   绕线规则(没有太懂,两个枚举没看出不一致的地方)
     * @param initialCapacity the estimate for the number of path segments
     *                        in the path 初始整个绘制过程中会绘制几条线
     * @throws IllegalArgumentException if {@code rule} is not either
     *         {@link #WIND_EVEN_ODD} or {@link #WIND_NON_ZERO}
     * @throws NegativeArraySizeException if {@code initialCapacity} is
     *         negative
     * @see #WIND_EVEN_ODD
     * @see #WIND_NON_ZERO
     * @since 1.2
     */
    public GeneralPath(int rule, int initialCapacity) {
        super(rule, initialCapacity);
    }

要创建空GeneralPath实例调用new GeneralPath(),然后使用以下方法向形状添加线段:

  • moveTo(float x, float y)– 将路径的当前点移动到给定点

假如当前画笔是在(10,10)坐标位置,直接将画笔移动至(x,y)坐标点,注意是移动,这两点之间不划线

  • lineTo(float x, float y)– 向当前路径添加线段

假如当前画笔是在(10,10)坐标位置,直接将画笔移动至(x,y)坐标点,并且在(10,10)到(x,y)之间画一条线

  • quadTo(float ctrlx, float ctrly, float x2, floaty2)– 将二次曲线段添加到当前路径

  • curveTo(float ctrlx1, float ctrly1, float ctrlx2, float ctrly2, float x3, floaty3)– 将三次曲线段添加到当前路径

  • closePath()– 关闭当前路径

就是将开始坐标和结束坐标用线连接起来

下面我们看几个实例

①、实例一:绘制不规则形状

代码:

        BufferedImage image = loadImage();
        Graphics2D graphics2D = image.createGraphics();
        graphics2D.setColor(Color.RED);

        /**
         * 设置需要绘制的点
         * x2Points和y2Points 两个数组长度一直,相同下标数值分别表示一个点的x和y轴
         * 本例有4个点(0,0) (100,50) (0,50) (100,0)
         */
        int x2Points[] = {0, 100, 0, 100};
        int y2Points[] = {0, 50, 50, 0};

        
        GeneralPath polyline =
                new GeneralPath(GeneralPath.WIND_NON_ZERO, x2Points.length);

        //画笔移动至 (0,0)坐标
        polyline.moveTo(x2Points[0], y2Points[0]);

        //然后从 (0,0)坐标开始 按顺序 绘制到目标点的线
        for (int index = 1; index < x2Points.length; index++) {
            polyline.lineTo(x2Points[index], y2Points[index]);
        }

        graphics2D.draw(polyline);

        graphics2D.dispose();
        image.flush();
        ImgUtil.write(image, new File(SAVE_FILE_PATH + "GeneralPath1.png"));

效果:

②、实例二:绘制不规则形状并且闭合

代码:相比实例一多出了”polyline.closePath();“效果就不一致

        BufferedImage image = loadImage();
        Graphics2D graphics2D = image.createGraphics();
        graphics2D.setColor(Color.RED);

        /**
         * 设置需要绘制的点
         * x2Points和y2Points 两个数组长度一直,相同下标数值分别表示一个点的x和y轴
         * 本例有4个点(0,0) (100,50) (0,50) (100,0)
         */
        int x2Points[] = {5, 100, 0, 100};
        int y2Points[] = {5, 50, 50, 0};


        GeneralPath polyline =
                new GeneralPath(GeneralPath.WIND_NON_ZERO, x2Points.length);

        //画笔移动至 (0,0)坐标
        polyline.moveTo(x2Points[0], y2Points[0]);

        //然后从 (0,0)坐标开始 按顺序 绘制到目标点的线
        for (int index = 1; index < x2Points.length; index++) {
            polyline.lineTo(x2Points[index], y2Points[index]);
        }

        polyline.closePath();
        graphics2D.draw(polyline);


        graphics2D.dispose();
        image.flush();
        ImgUtil.write(image, new File(SAVE_FILE_PATH + "GeneralPath2.png"));

③、实例三:绘制菱形

代码:


        BufferedImage image = loadImage();
        Graphics2D graphics2D = image.createGraphics();
        graphics2D.setColor(Color.RED);

        /**
         * 设置需要绘制的点
         * x2Points和y2Points 两个数组长度一直,相同下标数值分别表示一个点的x和y轴
         * 本例有4个点(5,55) (55,5) (105,55) (55,105)
         */
        int x2Points[] = {5, 55, 105, 55};
        int y2Points[] = {55, 5, 55, 105};


        GeneralPath polyline =
                new GeneralPath(GeneralPath.WIND_NON_ZERO, x2Points.length);

        //画笔移动至 (0,0)坐标
        polyline.moveTo(x2Points[0], y2Points[0]);

        //然后从 (0,0)坐标开始 按顺序 绘制到目标点的线
        for (int index = 1; index < x2Points.length; index++) {
            polyline.lineTo(x2Points[index], y2Points[index]);
        }

        polyline.closePath();
        graphics2D.draw(polyline);


        graphics2D.dispose();
        image.flush();
        ImgUtil.write(image, new File(SAVE_FILE_PATH + "GeneralPath3.png"));

绘制效果:

④、实例四:绘制五角星

五角星的绘制复杂的地方是在10个坐标点的计算,直接上代码

计算五角星10个坐标点的方法代码


    /**
     * 计算五角星10个坐标位置
     *
     * @param centerX 五角星中心点X轴
     * @param centerY 五角星中心点Y轴
     * @param x2Points  存储五角星10个点X轴
     * @param y2Points  存储五角星10个点Y轴
     *                  需要注意的是 第一个坐标必须指定
     * @return void
     * @author liuchao
     * @date 2023/3/14
     */
    private void calculateFivePointedStarPoint(double centerX, double centerY, double x2Points[], double y2Points[]) {
        //圆周率
        float pi = 3.141592653F;


        x2Points[1] = centerX - (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.cos((float) 36 / 360 * 2 * pi + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[1] = centerY + (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.sin((float) 36 / 360 * 2 * pi + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));

        x2Points[2] = centerX - (float) 30 *
                Math.cos((float) 36 / 360 * 2 * pi * 2 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[2] = centerY + (float) 30 *
                Math.sin((float) 36 / 360 * 2 * pi * 2 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));

        x2Points[3] = centerX - (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.cos((float) 36 / 360 * 2 * pi * 3 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[3] = centerY + (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.sin((float) 36 / 360 * 2 * pi * 3 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));

        x2Points[4] = centerX - (float) 30 *
                Math.cos((float) 36 / 360 * 2 * pi * 4 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[4] = centerY + (float) 30 *
                Math.sin((float) 36 / 360 * 2 * pi * 4 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));

        x2Points[5] = centerX - (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.cos((float) 36 / 360 * 2 * pi * 5 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[5] = centerY + (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.sin((float) 36 / 360 * 2 * pi * 5 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));

        x2Points[6] = centerX - (float) 30 *
                Math.cos((float) 36 / 360 * 2 * pi * 6 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[6] = centerY + (float) 30 *
                Math.sin((float) 36 / 360 * 2 * pi * 6 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));

        x2Points[7] = centerX - (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.cos((float) 36 / 360 * 2 * pi * 7 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[7] = centerY + (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.sin((float) 36 / 360 * 2 * pi * 7 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));

        x2Points[8] = centerX - (float) 30 *
                Math.cos((float) 36 / 360 * 2 * pi * 8 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[8] = centerY + (float) 30 *
                Math.sin((float) 36 / 360 * 2 * pi * 8 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));

        x2Points[9] = centerX - (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.cos((float) 36 / 360 * 2 * pi * 9 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
        y2Points[9] = centerY + (float) 10 / Math.cos((float) 36 / 360 * 2 * pi) *
                Math.sin((float) 36 / 360 * 2 * pi * 9 + Math.atan((float) Math.abs(y2Points[0] - centerY)
                        / (float) Math.abs(x2Points[0] - centerX)));
    }

绘制五角星代码


        /**
         * 五角星中心点位置
         */
        double centerX = 300D;
        double centerY = 60D;

        /**
         * 五角星10个点坐标
         * 第一个点坐标必须指定
         */
        double x2Points[] = {274D, 0D, 0D, 0D, 0D, 0D, 0D, 0D, 0D, 0D};
        double y2Points[] = {75D, 0D, 0D, 0D, 0D, 0D, 0D, 0D, 0D, 0D};

        calculateFivePointedStarPoint(centerX, centerY, x2Points, y2Points);


        BufferedImage image = loadImage();
        Graphics2D graphics2D = image.createGraphics();
        graphics2D.setColor(Color.RED);


        GeneralPath polyline =
                new GeneralPath(GeneralPath.WIND_NON_ZERO, x2Points.length);

        //画笔移动至 (0,0)坐标
        polyline.moveTo(x2Points[0], y2Points[0]);

        //然后从 (0,0)坐标开始 按顺序 绘制到目标点的线
        for (int index = 1; index < x2Points.length; index++) {
            polyline.lineTo(x2Points[index], y2Points[index]);
        }

        polyline.closePath();
        graphics2D.draw(polyline);


        graphics2D.dispose();
        image.flush();
        ImgUtil.write(image, new File(SAVE_FILE_PATH + "five-pointed-star.png"));

绘制效果:

大家看到五角星10个坐标点的计算方法是不是懵逼了,没错就是这么复杂,觉得有用的朋友一定要点赞加关注,感谢!!!!!!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈行动派

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值