本节书摘来自华章计算机《Java数字图像处理:编程技巧与应用实践》一书中的第1章,第1.1节,作者 贾志刚,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
第1章
Java Graphics及其API简介
在开始本书内容之前,笔者假设你已经有了面向对象语言编程的基本概念,了解Java语言的基本语法与特征,原因在于本书的所有源代码都是基于Java语言实现的,而且是基于Java开发环境运行与演示所有图像处理算法的。本书第1章到第3章是为了帮助读者了解与掌握Java 图形与GUI编程的基本知识与概念而写的。本章主要介绍Java GUI编程中基本的图形知识,针对GUI编程,Java语言提供了两套几乎并行的API,分别是Swing与AWT。早期的Java GUI编程中主要使用AWT的相关组件,但是AWT的功能并不是十分强大,而且严重依赖本地接口。于是在Java 1.3及后续版本中引入了Swing工具实现GUI编程,Swing中的组件大多数都是基于纯Java语言实现的,而不是通过本地组件实现的,所以它们是轻量级的GUI组件,同时Swing对图形与图像的支持操作也有很大的提高与增强。如何区分AWT组件与Swing组件?一个简单而且相当直观的方法是看Class的名称,Swing的组件大多数带有大写的前缀字母J。
Graphics作为Java的图形引擎绘制接口,几何形状、文字、图像的绘制都必须通过它完成,此外,Graphics还支持绘制过程的控制,可以设置画笔颜色、纹理、颜色填充方法、合成与裁剪路径及各种Stroke与Fill的属性等。用户程序通常都是通过Graphics来访问绘制引擎,从而实现各种图形与图像绘制的,因此可以说Graphics是Swing中最重要的接口对象。好吧,下面让我们一起揭开Graphics的神秘面纱。
1.1 什么是Java图形设备Graphics
简单地说Graphics是Java图形绘制引擎的访问接口,只有通过它才可以访问到Java GUI的图形绘制引擎,实现图形的绘制与绘制过程的控制。
1.1.1 Graphics概述
Grahpics的功能大致可以分为两类,第一类是通过Draw或Fill方法来实现各种图形的绘制与填充,第二类是设置各种绘制属性,最简单的包括设置字体、颜色、填充方法等。此外,在Java 2D中Graphics还可以被转型为Graphics2D对象,从而提供更高精度的图形绘制,设置更多绘制属性来控制绘制过程。
1.1.2 Graphics图形设备的获取、使用和销毁
在Java Swing中正确获取Graphics对象的方法有两种。
第一种是从BufferedImage对象实例中获取,其代码如下:
第二种方法是通过重载Swing组件的paintComponent(Graphics g)或paint(Graphics g)方法来实现,个人推荐采用重载paintComponent(Graphics g)方法来实现,因为重载paint(Graphics g)是AWT时代遗留下来的产物,是一个重量级绘制重载,通常用于Canvas对象的重载绘制。
除了以上两种推荐的做法以外,笔者经常还看到直接通过Swing组件的getGraphics去获取Graphics对象的,这样做的坏处是一旦该组件没有被显示,所对应的Graphics对象将返回NULL。而且这种做法常会导致一些意想不到的错误,所以应该尽量避免这么做。下面提供一个这么做导致错误的代码示例,如下:
JButton okBtn = new JButton(“OK”);
okBtn.getGraphics().drawRect(0,0,20,20); // NullPointerException
在获取了Java图形设备对象Graphics之后,就可以调用它的绘制方法来实现图形绘制与填充了。简单的示例代码如下:
public void paintComponent(Graphics g)
{
g.setColor(Color.BLUE);
g.drawRect(10, 10, 50, 50);
}
上述代码将会绘制一个蓝色边框的矩形,其中“10,10”表示矩形开始绘制的左上角位置,“50,50”分别代表矩形的长度与高度。
在使用完Graphics对象以后,请记得一定要销毁图形设备对象,可通过调用方法dispose()来释放图形绘制时所使用的任何资源。特别是当图形设备是从你自己的Buffered-Image对象中创建出来的时候,记得使用完以后一定要调用dispose()方法来释放资源。假设没有调用dispose(),一般情况下Java的GC也会自动调用来释放资源,但还是强烈建议在绘制完成以后显式调用dispose()方法来确保被使用的资源得到及时释放而不是依赖Java GC。原因在于当你使用的Graphics来自BufferedImage对象时,Graphics对象不会被自动销毁,而依赖GC调用来清理与释放资源并不能保证及时释放,可能导致程序堆内存过度消耗产生OOM(Out of Memory)问题。
1.1.3 Java Swing Graphics2D的重要属性
Graphics可以向下转型为Graphics2D对象,可以通过设置绘制属性来实现对图形绘制质量的控制。其接受对象为RenderingHints的枚举类型,通过方法setRenderingHint(Rendering-Hints.key, RenderingHints.value)来实现,一般常用的Key与Value有如下形式。
控制图形边缘反锯齿时,RenderingHints.KEY_ANTIALIASING的值为:
RenderingHints.VALUE_ANTIALIAS_ON表示支持边缘反锯齿。
RenderingHints.VALUE_ANTIALIAS_OFF表示不支持边缘反锯齿。
控制文字或文本边缘反锯齿时,RenderingHints.KEY_TEXT_ANTIALIASING的值为:
RenderingHints.VALUE_ TEXT_ANTIALIAS_ON表示支持文本边缘反锯齿。
RenderingHints.VALUE_ TEXT_ANTIALIAS_OFF表示不支持文本边缘反锯齿。
控制图像的插值方法时,KEY_INTERPOLATION的值为:
RenderingHints.VALUE_INTERPOLATION_BICUBIC表示使用双立方插值方法。
RenderingHints.VALUE_ INTERPOLATION_BILINEAR表示使用双线性插值方法。
RenderingHints.VALUE_ INTERPOLATION_NEAREST_NEIGHBOR表示使用临近点插值方法。
控制绘制方法时,KEY_RENDERING的值为:
RenderingHints.VALUE_ RENDER_QUALITY表示支持绘制质量优先。
RenderingHints.VALUE_ RENDER_SPEED表示支持绘制速度优先。
控制绘制过程是否支持抖动时,KEY_DITHERING的值为:
RenderingHints.VALUE_ DITHER_DISABLE表示不支持抖动。
RenderingHints.VALUE_ DITHER_ENABLE表示支持抖动。
更多的绘制属性控制可以参考官方文档,需要强调的是,由于Java的跨平台属性导致并不是所有的RenderingHints设置都会起作用,因此有些属性可能只有在某些特定的平台才支持。但是最常见的图形与文本的反锯齿功能几乎所有的操作系统平台都支持!