Java Graphics2D的使用[亲测有效]

Java (58) 2023-03-26 20:04

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说Java Graphics2D的使用[亲测有效],希望能够帮助你!!!。
Java Graphics2D的使用[亲测有效]_https://bianchenghao6.com/blog_Java_第1张

Java Graphics2D的使用

文章目录

  • Java Graphics2D的使用
      • 前言
    • 一、Graphics2D基础方法使用
    • 二、绘制不规则多边形
    • 三、填充(图片)不规则多边形
    • 四、翻转图像(上下、左右180°)
    • 五、绘制文字,简单封装(其实就是drawString)
    • 六、【扩展】读取配置文件方法

前言

​ 最近实习任务要转换一个绘图相关的.net程序,大概是这样

Java Graphics2D的使用[亲测有效]_https://bianchenghao6.com/blog_Java_第2张

一开始挺怕的毕竟没弄过图形相关的,之前学习Java的时候碰到也说无脑跳过,大概一周多一点时间我大概解决了这个任务,虽然这个程序难点主要是坐标/比例尺转化未平面绘图坐标,但我觉得学到的Graphics2D相关经验也说非常宝贵的,记录下相关方法,下图是我完成后的

Java Graphics2D的使用[亲测有效]_https://bianchenghao6.com/blog_Java_第3张

一、Graphics2D基础方法使用

  • 创建对象

    //创建图片对象
              BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
              //基于图片对象打开绘图
              Graphics2D graphics = image.createGraphics();
    
  • 常用的前置设置(不设置线段/文字不是横竖(就是斜的)的时候会有锯齿)

      //消除文字锯齿
      g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
      //消除画图锯齿
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
  • 创建矩形(未绘制)

    //声明并创建矩形对象,矩形的左上角是(20,30),宽是300,高是40 
    Rectangle2D back = new Rectangle2D.Double(20,30,300,40);
            graphics.fill(back);
    
  • 创建制圆(未绘制)

    //声明并创建圆对象,矩形的左上角是(20,30),宽是100,高是100 
    Ellipse2D.Double ellipse = new Ellipse2D.Double(20, 20, 100, 100);
             graphics.draw(ellipse);
    
  • 创建线段(未绘制)

    // 参数就是两个点的xy坐标 x1,y1,x2,y2
    Line2D.Float line = new Line2D.Float(10, 10, 20, 20);
    
  • 绘制 - 基本常用的就是draw(绘制边线) fill(填充:填充内容根据前置设置而定)

      // 前置可以进行线条粗细、字体大小、画笔颜色等属性的设置
            // 设置画笔颜色
            graphics.setColor(Color.WHITE);
            // 设置画笔粗细
            Stroke stroke=new BasicStroke(2.0f);//设置线宽为2.0
            graphics.setStroke(stroke);
            // 设置字体大小
            graphics.setFont(new Font("仿宋",Font.BOLD,fontSize));
            // 绘制文字 content-内容 xy坐标
             // 文字画入画布中 
            graphics.drawString(content, x,y);
    // 直接放入图形对象
    graphics.draw(图形对象);
    // 可以写入本地文件(文件名无路径默认/src下)
            //保存图片 JPG表示保存格式
            ImageIO.write(image,"JPEG",new FileOutputStream("a.jpg"));
            ImageIO.write(image, "png", new File("abcd.png"));
    
    

二、绘制不规则多边形

不多说直接上代码

    /** * 绘制多边形 * @param pointList 多边形的坐标集 * @return * @throws FileNotFoundException * @throws IOException */
    public BufferedImage drawPolygon(List<Point> pointList) throws FileNotFoundException, IOException { 
   
        //得到图片缓冲区
        BufferedImage image = new BufferedImage
                //INT精确度达到一定,RGB三原色,宽度512,高度512
                (1000,600,BufferedImage.TYPE_INT_RGB);

        //得到它的绘制环境(这张图片的笔)
        Graphics2D g2 = (Graphics2D) image.getGraphics();

        //消除文字锯齿
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //设置画笔白色
        g2.setColor(Color.white);
        //全图填充白色底图
        g2.fillRect(0, 0, image.getWidth(), image.getHeight());
        
        //shape的子类,表示一个形状
        GeneralPath gp=new GeneralPath();
        // 确定两个点
        JsonJZD p1=pointList.remove(0);
        JsonJZD p2=pointList.remove(0);

        //两个点画第一条直线
        gp.append(new
                  Line2D.Double(p1.getX(),p1.getY(),p2.getX(),p2.getY()),true);
        //直线分别与余下的点相连
        for(Point point: pointList){ 
   
            gp.lineTo(point.getX(),point.getY());
        }
        //闭合图形
        gp.closePath();
        //设置画笔黑色
        g2.setColor(Color.BLACK);

        // 填充网格- 填充内容来自图片
        image = fillPolygon(image,gp);
        //填充图形
        g2.draw(gp);

        // 翻转图形 - 上下翻转180°
// image = imageMisro(image,UPSIDE_DOWN);

        // 释放g2资源
        g2.dispose();




// ImageIO.write(image,"JPEG",new FileOutputStream("a.jpg"));//保存图片 JPEG表示保存格式
// ImageIO.write(image, "png", new File("abcd.png"));
        return image;
    }

三、填充(图片)不规则多边形

​ 可以看到我的需求有需要使用网格填充图形,这种填充图像的,网上找的都是C或者C#的代码,而且使用的是多边形扫描线填充算法简单剖析(Scan-Line Filling),本来也是想写个这个方法,奈何数学忘得差不多+还是想偷懒,就想继续寻找, 终于,找到了使用TexturePaint类填充图像的写法,处于便于修改填充图像的目的,我就通过properties获取图片路径,具体流程是这样

  1. 读取配置文件,获得图片路径

  2. 根据图片路径获取图片的BufferedImage对象

  3. 使用获取的图片对象创建TexturePaint填充笔

  4. 使用获取的填充笔对象设置到graphics2D对象里

  5. 使用graphics2D对象的fill方法填充目标不规则多边形

    具体代码如下(其中第二个方法是读取配置文件的方法)

    BufferedImage对象可以像二一样直接创建,这里选择传参

        /** * 填充不规则多边形 - 固定填充 src/main/resources/img/fillImg2.jpg * @param image BufferedImage对象 * @param gp 多边形 * @return * @throws IOException */
        private BufferedImage fillPolygon(BufferedImage image, GeneralPath gp) throws IOException { 
         
    
            // 0.读取配置文件
            String url = getProperties("src/main/resources/fill-Img.properties","fill-img.url");
            System.out.println("url:" + url);
            // 1.得到它的绘制环境(这张图片的笔)
            Graphics2D g2 = (Graphics2D) image.getGraphics();
            // 2.填充网格- 填充内容来自图片
            BufferedImage fillImg = ImageIO.read(new File(url));  //要填充图片
            // 创建矩形(用来放图片的框)
            Rectangle2D examp = new Rectangle2D.Double(100,100,50,50);
            // 把图片填充进矩形(矩形大小就是上面矩形的大小) -》 制作成画笔
            TexturePaint tp = new TexturePaint(fillImg,examp); //Rectangle2D是img大小
            g2.setPaint(tp);//设置g2的画笔为图片样式的
            g2.fill(gp);//gp不规则图形
            return image;
        }
    
      /** * 根据key读取value * * @Title: getProperties * @Description: 使用缓冲输入流读取配置文件,然后将其加载,再按需操作 * 绝对路径或相对路径, 如果是相对路径,则从当前项目下的目录开始计算, * 如:当前项目路径/config/config.properties, * 相对路径就是config/config.properties * * @param filePath * @param keyWord * @return * @return String * @throws */
         public static String getProperties(String filePath, String keyWord){ 
         
           Properties prop = new Properties();
               String value = null;
             try { 
         
                         // 通过输入缓冲流进行读取配置文件
                       InputStream InputStream = new BufferedInputStream(new FileInputStream(new File(filePath)));
                       // 加载输入流
                        prop.load(InputStream);
                   // 根据关键字获取value值
                          value = prop.getProperty(keyWord);
                    } catch (Exception e) { 
         
                   e.printStackTrace();
                     }
                  return value;
                }
    

四、翻转图像(上下、左右180°)

    /** * 镜像处理 180°水平和垂直翻转 * type = 0 表示上下翻转,type = 1 表示左右翻转 * @param bufferedimage 需要翻转的BufferedImage对象 * @param type * @return */
    public static BufferedImage imageMisro(BufferedImage bufferedimage,int type ) { 
   
        try
        { 
   
            int w = bufferedimage.getWidth();
            int h = bufferedimage.getHeight();

            int[][] datas = new int[w][h];
            for (int i = 0; i < h; i++) { 
   
                for (int j = 0; j < w; j++) { 
   
                    // getRGB 获取图像中的像素整数值 二进制格式
                    datas[j][i] = bufferedimage.getRGB(j, i);
                }
            }
            int[][] tmps = new int[w][h];
            if (type == 0) { 
   
                for (int i = 0, a = h - 1; i < h; i++, a--) { 
   
                    for (int j = 0; j < w; j++) { 
   
                        tmps[j][a] = datas[j][i];
                    }
                }
            } else if (type == 1) { 
   
                for (int i = 0; i < h; i++) { 
   
                    for (int j = 0, b = w - 1; j < w; j++, b--) { 
   
                        tmps[b][i] = datas[j][i];
                    }
                }
            }
            for (int i = 0; i < h; i++){ 
   
                for (int j = 0; j<w ;j++){ 
   
                    bufferedimage.setRGB(j, i, tmps[j][i]);
                }
            }


            return bufferedimage;
            //ImageIO.write(bufferedimage, "jpg", file);

        } catch (Exception e) { 
   
            e.printStackTrace();
        }
        return null;
    }

五、绘制文字,简单封装(其实就是drawString)

 /** * content 需要绘制的文字 * interval 文字两端空余像素 * fontSize 文字大小 * x 绘制起始点x * y 绘制起始点y * g2 graphics2D对象 */
    public void drawWord(String content,int fontSize, float x, float y,Graphics2D g2) { 
   
        //消除文字锯齿
  g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2.setPaint(Color.BLACK);
        g2.setFont(new Font("仿宋",Font.BOLD,fontSize));

        g2.drawString(content, x,y); // 文字画入画布中
    }

六、【扩展】读取配置文件方法

这里推荐一个博主记录的比较全面[Java 读取 .properties 配置文件的几种方式](https://www.cnblogs.com/sebastian-tyd/p/7895182.html)

发表回复