本节书摘来自华章计算机《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);
}
}