我们在使用谷歌,百度的时候,会发现它们的输入提示框为检索提供极大的方便。接下来的例子里我们将使用Swing来实现这一功能。老规矩,我们结合例子来解释,大家可以在文章的结尾下载到它,项目的名称叫 FilterList。大家不妨先运行一下例子再接着往下看。
这个例子中一共有三个类,FilterTest 很简单,只是用来显示例子的外壳,让我们把注意力放在 FilterField 和 FilterField 上。FilterField 是一个 JTextField 的子类。输入某些字符后就会出现过滤提示框了。那么如何做到一输入就自动过滤呢?我们将
FilterField 现实 DocumentListener 接口,这个接口有三个抽象方法:
public void insertUpdate(DocumentEvent e) {}
public void removeUpdate(DocumentEvent e) {}
public void changedUpdate(DocumentEvent e) {}
从名称上就可以看出,当输入框的文字发生变化的时候就会触发相应的方法。这样只有你对输入框中的文字做出修改,就会触发过滤的操作。我们在
FilterTest 里面为
FilterField
添加一个
DocumentListener 监听器,这个监听器是
FilterField
本身,
ftField.getDocument().addDocumentListener(ftField)。
我们在
FilterField
中使用 Popup 对象来实现弹出的效果。
Popup
对象包含一个 JPanel 对象,变量名称叫做 popPanel,popPanel 中只放一个 JList 对象,过滤出来的结果都放在这个JList中。有符号条件的结果,
Popup
对象就会显示,否则不显示,那么让
Popup
对象显示和隐藏的方法是showPopup 和 hidePopup 方法。showPopup 方法中会计算出
Popup
对象显示的坐标,并结合过滤的结果来设置大小尺寸,关键代码为:
//通过Swing计算出准确的坐标位置
SwingUtilities.convertPointToScreen(show, this);
//计算
Popup
对象的高度,长度和
FilterField
一样
int height = this.listModel.getSize() * JLIST_CELL_HEIGHT + 3;
//通过Swing创建
Popup
对象
pop = PopupFactory.getSharedInstance().getPopup(this, popPanel, x, y - 1);
接着我们为
FilterField对象添加了AncestorListener,FocusListener,ComponentListener监听器,为的是在
FilterField对象发生焦点,位置,尺寸变化的时候及时对
Popup
对象做出控制(这里只是将其隐藏)。我们还为
FilterField添加了
KeyListener监听器,又为JList对象添加了MouseMotionListener,MouseListener监听器,目的是为了配合用户的键盘和鼠标操作——用户可以通过键盘和鼠标来选择过滤的结果。
接下来,让我们看看ListModel。这个类是AbstractListModel的子类,它是
FilterField对象中的JList对象的Model。我们将covers目录下的图片名称作为我们的数据库来检索,在
ListModel的
构造方法中来完成者项工作,所有的书名都放在一个数组中。ListModel最重要的方法是filter方法,它会检索匹配的项,并通知JList内容有改变:
this.fireContentsChanged(this, 0, this.getSize())。JList收到通知后会重新绘制自己。我们给JList设置了一个叫做FilterListOnlyTextCellRenderer的ListCellRenderer。这样我们可以把JLabel作为数据项放入JList,为什么这么做呢?因为可以控制大小,并且可以在JLabel中放入我们想放入的东西,比如图片,下面就会用到。
程序运行的效果图如下:

我们可以把这个例子改进得更好点,在提示框出现的时候,我们希望最左边可以出现书的缩略图。我们在
FilterField中提供了另一个ListCellRenderer,叫做FilterListForImageCellRenderer。如果你想看到这个例子,那么需要做两步。给list换一个
ListCellRenderer:list.setCellRenderer(new FilterListForImageCellRenderer()),将JLIST_CELL_HEIGHT常量的值改为39。这两行代码都有保留,但被注释掉了,需要读者自己调整一下。
程序运行的效果图如下:

这个例子只是一个小小的提示,使用例子中介绍的几个重要知识点,我们可以做出各种效果的提示框,以及其他工具。
例子FilterList下载
http://chenchaobox.blog.163.com/blog/static/604375902012713112722524/