具有可过滤功能的JList组件【Swing】

2023-11-02 17:18

本文主要是介绍具有可过滤功能的JList组件【Swing】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【场景】:在一个列表中,可以通过输入某个字符,而动态过滤列表中项的显示。当然,动态显示的项都是包含用户输入的字符!在此,实现的功能非常简单,没有 更多的复杂逻辑。仅是为学习者提供一些案例。可以从中进行自己需要的扩展。
【关系图】:



在Swing中,想构建自己的组件,最简单的就是继承现有的组件,再做可定制的功能扩展,也不需要做太多额外的工作,因为Swing为我们提供了良好的可 扩展性。上图,简略的说明了待开发的可过滤的列表关系类图。以下做一些简单的描述:
【FilteredList】:继承了JList,其中类FilteredModel与FilteredTextField是他的内部类实现。在这里使用 内部类是为了能够方便的访问到FilteredList外部数据,减少了与外部类的交互,在此不能确定的说这种方式是好是坏,其中的衡量就留给用户了。
【FilteredModel】:继承了AbstractListModel,FilteredList中的内部类,并作为其的一个属性存在。作用是保存 展现在列表中的数据,并且能做动态更新。
【FilteredTextField】:继承了JTextFiled,很显然的就是一个输入框,只是实现了一个DocumentListener接口, 做到实时监听用户输入的任何动作:插入、删除、修改等。在用户触发这个监听时,就需要和FilteredModel进行交互,动态变化 FilteredList中的数据显示。

【编码实现】
FilteredModel
在这个Model中主要的是设置一个filteredItems 属性,用来保存包含了用户输入字符的列表项;另一个items属性,保存列表原始的所有项。关键的算法是方法refilter():实时对用户输入进行过 滤,并把结果添加到filteredItems 中。
private class FilterModel extends AbstractListModel {
private List items;
private List filteredItems;
public FilterModel() {
items = new ArrayList();
filteredItems = new ArrayList();
}

public void addElement(Object o) {//添加一个项到列表中
items.add(o);
refilter();//每添加一个项就更新filterItems
}

private void refilter() {
filteredItems.clear();
String item = getFilterField().getText();
for (int i = 0; i < items.size(); i++) {
if (items.get(i).toString().toUpperCase().indexOf(item, 0) != -1
|| items.get(i).toString().toLowerCase().indexOf(item,
0) != -1) {
filteredItems.add(items.get(i));
}
}
fireContentsChanged(this, 0, filteredItems.size());
}

@Override
public Object getElementAt(int index) {
if (index < filteredItems.size()) {
return filteredItems.get(index);
}
return null;
}

@Override
public int getSize() {
return filteredItems.size();
}
}


【FilterField】
private class FilterField extends JTextField implements DocumentListener {
public FilterField(int width) {
super(width);
getDocument().addDocumentListener(this);
}

@Override
public void changedUpdate(DocumentEvent e) {
model.refilter();//更新列表的显示数据,下同
}

@Override
public void insertUpdate(DocumentEvent e) {
model.refilter();
}

@Override
public void removeUpdate(DocumentEvent e) {
model.refilter();
}
}

【FilteredList】
public class FilteredList extends JList {
private FilterModel model;

private FilterField filterField;

public FilteredList() {
model = new FilterModel();
setModel(model);
filterField = new FilterField(20);
}

public void addItem(Object o) {
model.addElement(o);
}

public FilterField getFilterField() {
return filterField;
}
}
可见,FilteredList 实现起来非常的简单,只需定义前面已经创建出来的组件作为其属性。并更换Model。 使用自己实现的具有可过滤功能的Model。
下面是一段测试代码:
public static void main(String[] args) {
String[] listItems = { "Chris", "Joshua", "Daniel", "Michael", "Don",
"Kimi", "Kelly", "Keagan" };
JFrame frame = new JFrame("FilteredJList");
frame.getContentPane().setLayout(new BorderLayout());
// populate list
FilteredHistoryList list = new FilteredHistoryList();
for (int i = 0; i < listItems.length; i++)
list.addItem(listItems[i]);
// add to gui
JScrollPane pane = new JScrollPane(list,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
frame.getContentPane().add(pane, BorderLayout.CENTER);
frame.getContentPane().add(list.getFilterField(), BorderLayout.NORTH);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

【小结】
在这里实现的只是为一个JList附加了一层特定的功能,当然,我们不能停留在仅仅学会如何编写这功能的代码上,还要搞清楚内部如何实现,最终是为什么要 如此去做。
在这里,使用继承机制,接口实现等,都是利用类库成熟的组件类,如此就能复用很多特性。我们需要的是JList上加一层额外的功能,那么当然需要继承自 JList,使他俩具有血缘关系啦,方便管理吗!从这里也可以感受到Swing编码的一种感觉:数据与展示层划分清晰,展示与数据没有耦合在一块。当然, 可以说,在这个例子中没有做的很好,也没有作出具体的层次优化,读者可以自己试一试……

【参考资料】:《Swing Hacks》 By Chris Adamson , Joshua Marinacci

这篇关于具有可过滤功能的JList组件【Swing】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/332102

相关文章

SpringBoot整合DeepSeek实现AI对话功能

《SpringBoot整合DeepSeek实现AI对话功能》本文介绍了如何在SpringBoot项目中整合DeepSeekAPI和本地私有化部署DeepSeekR1模型,通过SpringAI框架简化了... 目录Spring AI版本依赖整合DeepSeek API key整合本地化部署的DeepSeek

Python实现多路视频多窗口播放功能

《Python实现多路视频多窗口播放功能》这篇文章主要为大家详细介绍了Python实现多路视频多窗口播放功能的相关知识,文中的示例代码讲解详细,有需要的小伙伴可以跟随小编一起学习一下... 目录一、python实现多路视频播放功能二、代码实现三、打包代码实现总结一、python实现多路视频播放功能服务端开

css实现图片旋转功能

《css实现图片旋转功能》:本文主要介绍了四种CSS变换效果:图片旋转90度、水平翻转、垂直翻转,并附带了相应的代码示例,详细内容请阅读本文,希望能对你有所帮助... 一 css实现图片旋转90度.icon{ -moz-transform:rotate(-90deg); -webkit-transfo

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

Java CompletableFuture如何实现超时功能

《JavaCompletableFuture如何实现超时功能》:本文主要介绍实现超时功能的基本思路以及CompletableFuture(之后简称CF)是如何通过代码实现超时功能的,需要的... 目录基本思路CompletableFuture 的实现1. 基本实现流程2. 静态条件分析3. 内存泄露 bug

四种Flutter子页面向父组件传递数据的方法介绍

《四种Flutter子页面向父组件传递数据的方法介绍》在Flutter中,如果父组件需要调用子组件的方法,可以通过常用的四种方式实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录方法 1:使用 GlobalKey 和 State 调用子组件方法方法 2:通过回调函数(Callb

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf