《Java数字图像处理:编程技巧与应用实践》——1.4 Swing Java 2D的其他高级特性介绍

简介:

本节书摘来自华章计算机《Java数字图像处理:编程技巧与应用实践》一书中的第1章,第1.4节,作者 贾志刚,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

1.4 Swing Java 2D的其他高级特性介绍

1 . Stroke接口

Stroke是Graphics2D的API接口,用来实现图形的描边修饰,在Java 2D中只有一个完成Stroke接口的类BasicStroke,如果有需要,可以自己完成Stroke接口,实现自定义的Stroke类。如何使用Stroke的实现类?方法如下:

1)调用Graphics2D 的setStroke()方法,传入一个实例化的Stroke对象。
2)调用draw()方法,传入要绘制的几何形状。

BasicStroke的对象构造函数代码如下:

// 创建Stroke对象实例
float[] dash = {10.0f, 5.0f, 3.0f};
Stroke dashed = new BasicStroke(2.0f, BasicStroke.CAP_BUTT,
    BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f);

其中:

  • 第一个参数2.0f表示Stroke的宽度。
  • 第二个参数声明Stoke的结束方式,BasicStroke.CAP_BUTT表示如果不是闭合区域则不做任何修饰,直接结束绘制,BasicStroke.CAP_ROUND表示如果不是闭合则添加圆角帽线,然后结束。
  • 第三个参数表示线的连接方式,此处为JOIN_MITER。
  • 第四个参数指定Stoke线段的长度,此处线段长度为10。
  • 第五个参数声明点线模式,此处点线模式dash为不等长线段。
  • 第六个参数声明位移,0.0表示位移间隔为零。

更详细的参数说明可以参考JDK的官方文档,下面的代码通过创建BasicStroke实例对象来绘制一个虚线矩形:

// 创建Stroke对象实例
float[] dash = {10.0f, 5.0f, 3.0f};
Stroke dashed = new BasicStroke(2.0f, BasicStroke.CAP_SQUARE,
            BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f);
    
// 设置Graphics2D的Stroke对象引用
g2.setStroke(dashed);
    
// 创建形状
Shape rect2D = new RoundRectangle2D.Double(50, 50, 
                    300, 100, 10, 10);
g2.draw(rect2D);

2 . Texture Fill接口

Texture Fill即纹理填充,Graphics2D提供了setPaint()方法来设置纹理填充,通过fill()方法可实现对几何形状的填充。前面讲到的两种填充方式分别为颜色填充与渐变填充,这里将重点介绍纹理填充的类TexturePaint创建与使用。

TexturePaint通过构造一个BufferedImage对象作为纹理来填充几何形状,因为Buffered-Image对象数据将被拷贝到TexturePaint中,所以BufferedImage对象设置得比较小为好。实例化一个TexturePaint对象的代码如下:

Rectangle2D rect = new Rectangle2D.Double(10,10,200,200);
TexturePaint tp = new TexturePaint(image, rect)

其中image表示一个BufferedImage实例,rect表示截取作为纹理的区域。
使用实例化的TexturePaint来完成对矩形区域填充的代码如下:

// Texture Fill
Rectangle2D rect = new Rectangle2D.Double(10,10,200,200);
TexturePaint tp = new TexturePaint(image, rect);
g2.setPaint(tp);
g2.fill(rect2D);

3 . Font属性

Java 2D支持绝大多数常见字体的创建与属性值的修改调整,可通过Graphics2D setFont()方法来实现绘制字体的修改,同时Graphics2D绘制引擎还支持自定义的外部字体文件*.ttf的动态加载与使用。只要在使用之前加载字体文件即可,使用下面的代码可实现字体文件加载:

public Font loadFont() throws FontFormatException, IOException 
{
    String fontFileName = "AMERSN.ttf";
    InputStream is = this.getClass().
            getResourceAsStream(fontFileName);
    Font actionJson = Font.createFont(Font.TRUETYPE_FONT, is);
    Font actionJsonBase = actionJson.deriveFont(Font.BOLD, 16);
    return actionJsonBase;
}

字体加载与使用的完整代码如下:

package com.book.chapter.one;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.io.IOException;
import java.io.InputStream;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class FontDemo extends JPanel {

private static final long serialVersionUID = 1L;

public FontDemo() {
        super();
}

public void paintComponent(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    // 反锯齿
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON);
    // 设置画笔颜色
    g2d.setPaint(Color.BLUE); 
    try {
        g2d.setFont(loadFont());
    } catch (FontFormatException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    g2d.drawString("Font Demo", 50, 50);
    g2d.dispose(); // 释放资源
}

public Font loadFont() throws FontFormatException, 
IOException {
    String fontFileName = "AMERSN.ttf";
    InputStream is = this.getClass().
        getResourceAsStream(fontFileName);
    Font actionJson = Font.createFont(
            Font.TRUETYPE_FONT, is);
    Font actionJsonBase = 
        actionJson.deriveFont(Font.BOLD, 16);
    return actionJsonBase;
}

public static void main(String[] args) {
    JFrame ui = new JFrame("Font Demo Graphics2D");
    ui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ui.getContentPane().setLayout(new BorderLayout());
    ui.getContentPane().add(new FontDemo(), 
        BorderLayout.CENTER);
    ui.setPreferredSize(new Dimension(380, 380));
    ui.pack();
        ui.setVisible(true);
    }
}

4 . GeneralPath与自定义几何形状

Java 2D支持通过GeneralPath实现绘制任意的几何形状,使用GeneralPath提供的API接口绘制几何形状的步骤大致如下:

1)实例化GeneralPath对象。
2)调用moveTo()方法锚地开始点坐标。
3)调用lineTo()或curveTo方法绘制连接线。
4)调用closePath()方法完成几何形状绘制。

下面的代码实现了利用GeneralPath对象绘制一个红色五角星图案。

package com.book.chapter.one;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class GeneralPathDemo extends JPanel {
    /**
    * 
    */
    private static final long serialVersionUID = 1L;

    public GeneralPathDemo() {
        super();
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        // 反锯齿
        g2d.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING, 
                RenderingHints.VALUE_ANTIALIAS_ON);

        // 五角星的五个点坐标
        int x1 = this.getWidth() / 2;
        int y1 = 20;
        int x2 = this.getWidth() / 5;
        int y2 = this.getHeight() - 20;
        int x3 = x2 * 4;
        int y3 = this.getHeight() - 20;
        int x4 = 20;
        int y4 = this.getHeight() / 3;
        int x5 = this.getWidth() - 20;
        int y5 = y4;

        // 定义画点的顺序
        int x1Points[] = { x1, x2, x5, x4, x3 };
        int y1Points[] = { y1, y2, y5, y4, y3 };

        // 设置填充颜色
        g2d.setPaint(Color.RED);

        // 实例化GeneralPath对象
        GeneralPath polygon = new GeneralPath(
                GeneralPath.WIND_EVEN_ODD,
                x1Points.length);
        // 锚地开始第一个点
        polygon.moveTo(x1Points[0], y1Points[0]);
        // 顺序画出剩下点
        for (int i = 1; i < x1Points.length; i++) {
            polygon.lineTo(x1Points[i], y1Points[i]);
        }

        // 调用closePath形成一个封闭几何形状
        polygon.closePath();

        // 绘制它
        g2d.draw(polygon);

        // 释放资源
        g2d.dispose();
    }

    public static void main(String[] args) {
        JFrame ui = new JFrame("Demo Graphics");
        ui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ui.getContentPane().setLayout(new BorderLayout());
        ui.getContentPane().add(new GeneralPathDemo(),
                    BorderLayout.CENTER);
        ui.setPreferredSize(new Dimension(380, 380));
        ui.pack();
        ui.setVisible(true);
    }

}
相关文章
|
10天前
|
Java 调度
Java并发编程:深入理解线程池的原理与实践
【4月更文挑战第6天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将从线程池的基本原理入手,逐步解析其工作过程,以及如何在实际开发中合理使用线程池以提高程序性能。同时,我们还将关注线程池的一些高级特性,如自定义线程工厂、拒绝策略等,以帮助读者更好地掌握线程池的使用技巧。
|
13天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
14天前
|
缓存 算法 Java
Java内存管理与调优:释放应用潜能的关键
【4月更文挑战第2天】Java内存管理关乎性能与稳定性。理解JVM内存结构,如堆和栈,是优化基础。内存泄漏是常见问题,需谨慎管理对象生命周期,并使用工具如VisualVM检测。有效字符串处理、选择合适数据结构和算法能提升效率。垃圾回收自动回收内存,但策略调整影响性能,如选择不同类型的垃圾回收器。其他优化包括调整堆大小、使用对象池和缓存。掌握这些技巧,开发者能优化应用,提升系统性能。
|
15天前
|
存储 Java 关系型数据库
个人成绩信息管理系统【GUI/Swing+MySQL】(Java课设)
个人成绩信息管理系统【GUI/Swing+MySQL】(Java课设)
18 0
|
15天前
|
存储 Java 关系型数据库
社区医院管理服务系统【GUI/Swing+MySQL】(Java课设)
社区医院管理服务系统【GUI/Swing+MySQL】(Java课设)
24 1
|
15天前
|
存储 Java 关系型数据库
实验室设备管理系统【GUI/Swing+MySQL】(Java课设)
实验室设备管理系统【GUI/Swing+MySQL】(Java课设)
15 0
|
15天前
|
存储 Java 关系型数据库
冬奥会传统文化管理系统【GUI/Swing+MySQL】(Java课设)
冬奥会传统文化管理系统【GUI/Swing+MySQL】(Java课设)
8 0
|
15天前
|
存储 Java 关系型数据库
学生宿舍管理系统【GUI/Swing+MySQL】(Java课设)
学生宿舍管理系统【GUI/Swing+MySQL】(Java课设)
17 0
|
15天前
|
存储 Java 关系型数据库
学生管理系统【GUI/Swing+MySQL】(Java课设)
学生管理系统【GUI/Swing+MySQL】(Java课设)
15 0
|
15天前
|
存储 Java 关系型数据库
洗浴中心管理系统【GUI/Swing+MySQL】(Java课设)
洗浴中心管理系统【GUI/Swing+MySQL】(Java课设)
13 0