用JIcon装饰你的界面(一)

2014-11-23 20:27:43 · 作者: · 浏览: 22


如果说Swing Icon接口很简单,那么其强大的功能就更令人惊讶了。通过它,你可以用程序创建图标或在图标上进行各种操作、可以用不同的方式合并图标、或在现有组件中很容易地显示图标。让我们来开发一个组件,它可以让你显示一组图标,并可以在图标列表的各个状态中循环。在需要管理有很多元素的用户界面时(出于编辑或提供信息的目的,这些元素需要可视化地反映状态),该组件尤其有用。我们可以提供很多的例子,包括:一个日志文件条目列表,我们可以用一个彩色图标来反映每个条目的重要程度;或一个表,我们可以用一个列来反映每行的状态,包括可编辑状态、正常状态、包含在内(included )或不包含在内(excluded)的状态。

我们就不花时间来讲述如何将JIcon用做一个表、列表、树状单元绘制器(cell renderer)或编辑器了。可以说实现该功能并不难。如果我们要实现很多功能,本文的篇幅可能并不允许我们讲述太多。因此,我们将重点讲述如何构建一个可以在Icon元素中循环的简单的组件,如何运用一个你可以很容易侦听的模式来查看事件的变化或处理单元编辑器和绘制器组件。

在开发这个项目的过程中,我实现了几个Icon工具类(utility class),你可以下载它们。CompondIcon类可以让你合并任何两个图标,形式可以是并排的,或者一个图标在另一个图标的上面。DecoratorIcon可以让你用一个图标覆盖另一个图标,就像我们在快捷装饰的例子中所做的那样(见图1)。FilterIcon可以让你在绘制图标前,将一个图像过滤器(image filter)用于图标。在继续讲述前,让我们先来简要地看看每个类的功能是怎样的。Icon接口(Swing集合的一部分)是非常简单的:public interface Icon
{
public int getIconHeight();
public int getIconWidth();
public void paintIcon(
Component c, Graphics g,
int x, int y);
}
aspectratio="t"> Java/2003_03/JIcon/Image/fig1sm.gif" src="./0027.files/image001.gif">
只要调用组件知道图标的宽度和高度,它就可以很好地管理版面布局了。在绘制图标时,我们调用了paintIcon()方法。大多数情况下,你需要做的就是运用绘图环境(graphic context),在指定的x、y坐标上画图,将图像控制在由getIconWidth()和getIconHeight()方法返回的宽度和高度范围内。有时侯,可以访问绘制图标所位于的组件是很有用的;例如,我们可以用Component的getBackground()方法来取得背景颜色。

通过这个接口,我们可以很容易地从图像构建图标。实际上,Swing为此提供了ImageIcon。我们也可以很容易地在瞬间绘制图标。我提供了一个CheckBoxIcon对此加以说明,它可以绘制一个方框,该方框可以是空的、可以包含一个复选标记、或里面画有一个X标记。我们将用这些图标来说明多个状态。你可以在图1左边底部的方框中看到它的实际应用情况。如果你点击这个图标,它就会转换到每个可能出现的状态。在每个状态中,都运用了CheckBoxIcon的一个单独的实例。JIcon组件可以管理状态。

装饰图标
让我们很快地来看看很像容器的这三种图标的实现情况吧。它们可以让你组合、覆盖或调整图标,并将它们看做是单独的Icon实例。例如,你可以用CompoundIcon将多个图标放在一个通常只处理一个图标(如Jlabel或Jbutton)的Swing组件中。

DecoratedIcon类可以让你用一个图标覆盖另一个图标。该功能可以让你用一个较小的图标在九个可能的位置上来装饰一个大的图标:垂直方向上的TOP、BOTTOM或CENTER,以及水平方向上的LEFT、RIGHT或CENTER。构造器需要两个图标实例,并需要垂直对齐和水平对齐。我们会查看对齐是否有效,如果对齐不好,或装饰图标比被装饰图标大,你就会得到IllegalArgumentException异常。我们用GetIconWidth()和getIconHeight()来返回被装饰图标(两个图标中较大的那个)的宽度和高度。然后用paintIcon()方法先绘制被装饰的图标,再在指定的位置上绘制装饰图标。

FilterIcon类可以将一个ImageFilter用于一个指定的Icon实例。这是在构造器中实现的,另外,它还缓存了结果图像,以便在绘图时使用。我选用了ImageFilter,它是老的AWT的一部分,因为通过它,我们也可以用Java 2D最近提供的BufferedImageFiler(BuffereredImageFilter实现了ImageFilter接口)。接下来的工作就是返回所创建的图像的宽度和高度了,并在调用paintIcon()方法时,在x、y位置上画图。
我刚刚讲述的三个类可以让你在现有的Swing组件中显示合并的、被装饰的和被过滤的图标。我们可以嵌套这些Icon的实现形式,从而根据你的需要来组合或调整图标。遗憾的是,没有一个Swing组件可以提供多个状态视图,因此下面就让我们来看看如何实现这样一个组件,它可以让你处理多个图标来显示与你的应用程序相关的状态。

我们来看看所实现的JIcon中的两个重要的类,IconListModel和JIcon类本身IconListModel是个接口,它可以存储多个用于JIcon的图标。它可以以列表中当前索引的形式来管理数量不定的一列图标实例和当前选择的状态。要实现一个IconListModel接口,我们也必须将事件发送到任何注册的ChangeListener以便反映状态或Icon列表内容的变化,从而使视图(如JIcon)可以立即反映这些变化。注意,IconListModel扩展了Icon接口:public interface IconListModel
extends Icon
{
public int getIconCount();
public int getCurrentIndex();
public Icon getIcon(int index);
public void setIcons(
Icon[] icon);
public void addIcon(Icon icon);
public void removeIcon(
Icon icon);
public void setCurrentIcon(
int index);
public void addChangeListener(
ChangeListener listener);
public void removeChangeListener(
ChangeListener listener);
}

通过这个接口,我们就可以很容易地看到需要什么步骤来实现它了,即IconList的作用(见列表1)。我们运用了两个ArrayList实例:一个用来管理ChangeListener实例的列表,另一个用来管理Icon实例的列表。我们将宽度和高度值缓存起来,当调用Icon的getIconWidth()和getIc