《Java数字图像处理:编程技巧与应用实践》——第1章 Java Graphics及其API简介 1.1 什么是Java图形设备Graphics

简介:

本节书摘来自华章计算机《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对象实例中获取,其代码如下:

screenshot

第二种方法是通过重载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设置都会起作用,因此有些属性可能只有在某些特定的平台才支持。但是最常见的图形与文本的反锯齿功能几乎所有的操作系统平台都支持!

相关文章
|
1天前
|
安全 Java API
【性能与安全的双重飞跃】JDK 22外部函数与内存API:JNI的继任者,引领Java新潮流!
【9月更文挑战第7天】JDK 22外部函数与内存API的发布,标志着Java在性能与安全性方面实现了双重飞跃。作为JNI的继任者,这一新特性不仅简化了Java与本地代码的交互过程,还提升了程序的性能和安全性。我们有理由相信,在外部函数与内存API的引领下,Java将开启一个全新的编程时代,为开发者们带来更加高效、更加安全的编程体验。让我们共同期待Java在未来的辉煌成就!
21 11
|
2天前
|
安全 Java API
【本地与Java无缝对接】JDK 22外部函数和内存API:JNI终结者,性能与安全双提升!
【9月更文挑战第6天】JDK 22的外部函数和内存API无疑是Java编程语言发展史上的一个重要里程碑。它不仅解决了JNI的诸多局限和挑战,还为Java与本地代码的互操作提供了更加高效、安全和简洁的解决方案。随着FFM API的逐渐成熟和完善,我们有理由相信,Java将在更多领域展现出其强大的生命力和竞争力。让我们共同期待Java编程新纪元的到来!
22 11
|
1天前
|
Java API 数据处理
【Java的SIMD革命】JDK 22向量API:释放硬件潜能,让Java应用性能飙升!
【9月更文挑战第7天】 JDK 22向量API的发布标志着Java编程语言在SIMD技术领域的重大突破。这一新特性不仅释放了现代硬件的潜能,更让Java应用性能实现了飙升。我们有理由相信,在未来的发展中,Java将继续引领编程语言的潮流,为开发者们带来更加高效、更加强大的编程体验。让我们共同期待Java在SIMD技术的推动下开启一个全新的性能提升时代!
|
2天前
|
Java API 开发者
【Java字节码操控新篇章】JDK 22类文件API预览:解锁Java底层的无限可能!
【9月更文挑战第6天】JDK 22的类文件API为Java开发者们打开了一扇通往Java底层世界的大门。通过这个API,我们可以更加深入地理解Java程序的工作原理,实现更加灵活和强大的功能。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来!
|
4天前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。
|
5天前
|
API
|
6天前
|
数据采集 存储 前端开发
Java爬虫开发:Jsoup库在图片URL提取中的实战应用
Java爬虫开发:Jsoup库在图片URL提取中的实战应用
|
9天前
|
Java API
Java 8新特性:Lambda表达式与Stream API的深度解析
【7月更文挑战第61天】本文将深入探讨Java 8中的两个重要特性:Lambda表达式和Stream API。我们将首先介绍Lambda表达式的基本概念和语法,然后详细解析Stream API的使用和优势。最后,我们将通过实例代码演示如何结合使用Lambda表达式和Stream API,以提高Java编程的效率和可读性。
|
9天前
|
Java
java代码和详细的代码应用
代码块分为局部、构造、静态和同步代码块。局部代码块控制变量生命周期,例如 `int a` 只在特定代码块内有效。构造代码块用于创建对象时执行附加功能,避免构造方法中代码重复。静态代码块随类加载执行一次,常用于初始化操作。同步代码块确保多线程环境下方法执行的原子性,通过 `synchronized` 关键字实现。
19 3
|
8天前
|
存储 消息中间件 前端开发
Web2py框架下的神秘力量:如何轻松集成第三方API,让你的应用不再孤单!
【8月更文挑战第31天】在开发现代Web应用时,常需集成第三方服务如支付网关、数据存储等。本文将指导你使用Web2py框架无缝接入第三方API。通过实例演示从注册获取API密钥、创建控制器、发送HTTP请求到处理响应的全过程。利用`requests`库与Web2py的内置功能,轻松实现API交互。文章详细介绍了如何编写RESTful控制器,处理API请求及响应,确保数据安全传输。通过本教程,你将学会如何高效整合第三方服务,拓展应用功能。欢迎留言交流心得与建议。
23 1
下一篇
DDNS