【IT168 技术文章】

引言

许多应用程序都有包含图标的按钮,当按钮被选中或者鼠标移到按钮上时,按钮的图标会发生改变。Web 浏览器(如 Microsoft Internet Explorer)中的工具栏按钮就是这种现象的一个示例,其中的按钮图形是灰色的,当鼠标移动到按钮上时,图形会变成有颜色的。为了实现这种效果,要创建两组图形;一组用于正常状态,一组用于当鼠标移动到按钮上时的活动状态。然而,对于设计者来说,创建两组图形很费时间,并且意味着在需要更改图形时,必须对这两组图形做双倍的维护工作。更优化的办法是只使用一个图标,而图形效果则通过编程来实现,从而避免创建和维护一个单独图标的开销。本文描述的问题是针对如 图 1所示的向导页中的一组按钮的,当用户在每个按钮上悬停时,图形会发生改变以向用户表示该按钮是活动的。

图 1.Web Module 按钮在鼠标移动到它上面时处于活动状态并且图形已经改变。

在本文中,我们将说明如何通过使用 Java2D API 创建一个能够接受图像并创建所期望的效果的类来实现上述效果。这需要我们理解如何构造图像以及如何使用 AWT composite 来操作这些图像。

背景知识

javax.swing.JButton 类有一个布尔属性 rolloverEnabled 和一个 rolloverIcon 属性,后者的类型是 javax.swing.Icon。如果 rolloverEnabled 为 true,则当鼠标移动到按钮上时,rolloverIcon 的值就被用到该按钮的图形上。我们认定,一个优秀的解决方案应该有一个新的称为 RolloverImageIcon 的类,我们将在其构造函数中给它提供一张图像,然后,这个类会在绘制图标之前对图标进行操作。

这样,用于创建 rolloverButton 的代码将如下所示:

1 JButton button=newJButton(regularIcon);2 button.setRolloverEnabled(true);3 button.setRolloverIcon(newRolloverIcon(regularIcon));4

下一步是创建能够将初始图标包装起来并用 图 1所示的图形效果给图标着色的 RolloverIcon 类。

RolloverIcon

RolloverIcon 类将实现 javax.swing.Icon 接口,这个接口允许按钮的 rolloverIcon 属性取有效值并将初始图标存储到名为 fIcon 的实例变量中:

public class RolloverIcon implements Icon { protected Icon fIcon; {

一种变通的解决方案可能是创建 JButton 的子类,并将翻转效果封装到这个子类中,不过,通过将逻辑放到 RolloverIcon 类中,图形效果也可以在其它情形(如复选框或菜单项)中使用。假设想得到定制的子类,那么使用创建图形效果的逻辑并将这个逻辑委托给 RolloverIcon 的实例是个很简单的做法。

javax.swing.Icon 接口有三个方法: getIconWidth()、getIconHeight() 和 paintIcon(Component,Graphics,x,y) 。前两个方法可以委托给 RolloverIcon 正在为它创建图形效果的图标,因为翻转图像的大小将与原来图像的相同。

1 publicintgetIconHeight() {2 returnfIcon.getIconHeight();3 }4 publicintgetIconWidth() {5 returnfIcon.getIconWidth();6 }7

绘制(paint)方法是将对图形上下文进行实际绘图的方法。Component 参数代表正在为之绘制图标的控件,如 javax.swing.JButton 的实例。这个方法允许我们访问诸如控件的字体、插图等细节问题,以及我们在绘制图标时可能想考虑的其它属性。x 和 y 参数是在绘图表面上正在对该图形进行着色的位置。这些位置是绘图表面的绝对位置,与从组件的 getLocation() 返回的值不同,后者是按钮相对于其父容器的位置。绘图 API 需要使用绝对值,以便将它们传递到 paintIcon 方法中,避免不得不遍历组件的所有父容器来计算这些值。

graphics 参数是代表绘图表面的对象。虽然它的类型是 java.awt.Graphics,但它将是 java.awt.Graphics2D 的实例。Graphics2D 抽象类是 Java2D API 的一部分,它是出于向后兼容的目的作为 Java2 平台的一部分引入的,绘制方法的参数没有被重新转换为 Graphics2D 类型,尽管只要使用的 JRE 是 Java2 或更高版本就可以保证这个参数是 java.awt.Graphics2D 的实例。

paintIcon 方法的完全说明如下所示:

public void paintIcon(Component c, Graphics g, int x, int y);

RolloverIcon 实例将包装我们希望用 图 1中所示的图形效果绘制的初始图标。我们可以使用 Graphics2D 对象的 composite 属性做到这一点。composite 属性的类型是 java.awt.Composite 接口,并且由 Graphics2D 对象完成的对图形表面的所有图元绘图都直接通过对象的 composite 进行。存在许多现成的合成类,如其中有一个是用于创建异或(XOR)效果的。XORComposite 是 sun.java2d.loops.XORComposite 类,它的构造函数以要着色成异或效果的绘图的颜色为参数。每种颜色由红、绿和蓝值组成,如果用黑色(黑色的 r、g、b 值为 0、0、0)对颜色进行异或,则该颜色将被反转。要看到这种效果,绘制方法可以编写成如下所示:

1 publicvoidpaintIcon(Component c, Graphics g,intx,inty) {2 Graphics2D g2D=(Graphics2D)g;3 Composite oldComposite=g2D.getComposite();4 g2D.setComposite(newsun.java2d.loops.XORComposite(Color.black));5 fIcon.paintIcon(c,g,x,y);6 g2D.setComposite(oldComposite);7 }8

要对初始图标(保存在实例变量 fIcon 中)进行着色,我们只要遵从它的 paintIcon(Component,Graphics,int,int) 方法(这个方法已经将图形的 composite 预先设置为 XORComposite 对象)就行了。在操作图形对象的属性时,在完成之后将这些属性恢复成原来的值是一种很好的做法。在上面的方法中显示了这一点,我们在修改 composite 之前先将原来的 composite 存储起来,然后在完成修改之后将它恢复。如果您没有这样做,则 XORComposite 将会被保留在图形对象中,并且会影响到随后的所有绘图操作。

图 2显示了 XORComposite 的效果。上面那行按钮是 RolloverIcon 被设置成 rolloverIcon 属性的原来的按钮。下面那行按钮是被永久性地设置的,用来显示被设置成 icon 属性的 RolloverIcon 的结果。XORComposite 接受图标并通过用 0 对图标的每个像素进行异或来转换它。

图 2. XORComposite 可以用来控制如何对图标进行着色

异或的效果虽然不是如 图 1 所示的结果,但它确实表明了 composite 是如何负责在图标的绘图表面上进行着色的。如果我们创建自己的能让我们访问图标的精确着色的合成类,那我们就应该能够实现我们所期望的翻转效果。我们的类将叫做 RolloverComposite ,并且 paintIcon 方法可以在对初始图标进行着色之前将所期望的效果在图形对象中进行设置。

在实现 RolloverComposite 类之前,我们需要了解关于在 Java 语言中如何表示颜色以及如何将这些颜色绘制到绘图表面上去的更多知识。

JAVA2d用于,创建用于翻转效果的 Java2D 合成相关推荐

  1. python 申请内存空间、用于创建多维数组_python 申请内存空间,用于创建多维数组的实例...

    以三维数组为例 先申请1个一维数组空间: mat = [None]*d1 d1是第一维的长度. 再把mat中每个元素扩展为第二维的长度: for i in range(len(mat)): mat[i ...

  2. 独家 | 手把手教你用Python 3创建用于机器学习开发的Linux虚拟机(附安装教程代码)

    原文标题:How to Create a Linux Virtual Machine For Machine Learning Development With Python 3 作者:Jason B ...

  3. 独家 | 手把手教你用Python 3创建用于机器学习开发的Linux虚拟机(附安装教程代码)...

    Linux是使用Python进行机器学习开发的极佳环境.这些工具能够被简便快捷地安装,并且您可以直接开发和运行大型模型. 在本教程中,您将了解如何使用Python创建和安装用于机器学习的Linux虚拟 ...

  4. DCMTK:用于创建和加载增强型CT对象的测试

    DCMTK:用于创建和加载增强型CT对象的测试 用于创建和加载增强型CT对象的测试 用于创建和加载增强型CT对象的测试 #include "dcmtk/config/osconfig.h&q ...

  5. muduo网络库学习(七)用于创建服务器的类TcpServer

    目前为止,涉及到的绝大多数操作都没有提及线程,EventLoop,Poller,Channel,Acceptor,TcpConnection,这些对象的执行都是在单独线程完成,并没有设计多线程的创建销 ...

  6. 什么是Spring Boot以及为什么它是用于创建微服务的首选框架

    为什么要使用Spring Boot创建微服务? Spring Boot是Java领域众所周知的首选框架,用于创建Micro Services. 使用Spring引导框架,可以非常轻松地创建Java应用 ...

  7. Linux 命令之 rpmbuild -- 用于创建 rpm 格式的二进制软件包和源码软件包

    文章目录 一.命令介绍 二.命令选项 (一)从 specfile 建立 (二)从 tarball 包建立 (三)从 source package 包建立 (四)其它选项 (五)所有 rpm 都可使用的 ...

  8. c#网页自动化脚本语言,c# – 创建用于创建网页的脚本语言

    我正在创建一个用于创建网页的脚本语言,但不知道从哪里开始. 我有一个看起来像这样的文件: mylanguagename(main) { OnLoad(protected) { Display(img, ...

  9. html是一种用于创建网页的标准标记语言,html

    HTML.XML.XHTML 有什么区别? HTML是一种用于创建网页的国际通用的标准标记语言,用来展示数据:XML是一种标记语言,由相关人士自由决定的标记语言,即语言的可拓展性,设计用来传输及携带数 ...

最新文章

  1. json解析详解 java_Java解析Json数据的两种方式详解
  2. python按钮点击按一次触发一次_家里有个“按钮开关”能救命,必须每个月按一次,学会受用一生!...
  3. python 字符串大小写相关函数
  4. 服务器内存一般多大_性能调优第一步,搞定服务器硬件选型
  5. MySQL部署2002_MySQL入门02-MySQL二进制版本快速部署
  6. Linux配置环境变量source时报错:export `=‘ not a valid identifier的一般原因
  7. android style 中一些颜色的定义
  8. POJ3630——简单Trie树
  9. 信息学奥赛一本通(1412:二进制分类)
  10. 华为今年或发两款5G产品:5G CPE Win和5G随行WiFi
  11. Android——TextView属性XML详解
  12. Atitit java的异常exception 结构Throwable类
  13. 服务器与服务器之前文件传输,客户端与服务器的文件传输
  14. 解决:The proxy server received an invalid response from an upstream server
  15. 威纶通触摸屏如何打开并升级EB8000旧版本项目并更换触摸屏型号?
  16. IDEA如何导出war包
  17. 卸载vuecli3_针对遇到安装或卸载vue-cli失败的解决方案
  18. 北理工计算机学院奖学金公示,计算机学院2020年研究生国家奖学金拟推荐人选公示通知...
  19. js实现oss批量下载文件_jquery批量下载文件
  20. 为企业出海“搭桥”,汇量科技靠什么出圈?

热门文章

  1. 网页特效源码分析----标签云
  2. 2017年4月蓝桥杯模拟题
  3. compare()方法+使用compare方法
  4. 看板方法:向交警蜀黍学习怎么做软件
  5. 警察蜀黍动真格,抓捕内鬼390余人、黑客近百人
  6. 14.JDK底层Unsafe类是个啥东西?
  7. SN_Write_tool 使用说明文档
  8. Mapper的XML文件(一)
  9. 一千年的沉睡作者深秋葉蕭蕭
  10. 零基础也能快速上手的python实战项目----美多商城