本文目录导读:

JSpinnerListModel 是 Java Swing 中用于 JSpinner 组件的一种数据模型,它允许你通过一个列表(数组或 List)来定义 JSpinner 中显示的可用选项。
基本概念
JSpinnerListModel 允许用户通过向上/向下箭头或键盘在预定义的列表值之间循环选择。
主要构造方法
// 使用数组创建 JSpinnerListModel(Object[] items) // 使用 List 创建 JSpinnerListModel(List<?> items) // 使用 SpinnerListModel 的子类 SpinnerListModel(Object[] values) SpinnerListModel(List<?> values)
基本使用示例
示例1:使用数组创建简单列表
import javax.swing.*;
import java.awt.*;
public class JSpinnerListExample {
public static void main(String[] args) {
JFrame frame = new JFrame("JSpinner 列表模型示例");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
// 创建字符串数组
String[] items = {"星期一", "星期二", "星期三", "星期四", "星期五"};
// 创建 SpinnerListModel
SpinnerListModel model = new SpinnerListModel(items);
// 创建 JSpinner 并设置模型
JSpinner spinner = new JSpinner(model);
// 设置初始值(默认是第一个)
spinner.setValue("星期三");
frame.add(spinner);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
示例2:使用自定义对象
import javax.swing.*;
import java.awt.*;
public class CustomObjectListExample {
public static void main(String[] args) {
JFrame frame = new JFrame("自定义对象列表");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
// 创建自定义对象数组
Product[] products = {
new Product("笔记本电脑", 5999),
new Product("手机", 3999),
new Product("平板电脑", 2999)
};
// 创建列表模型
SpinnerListModel model = new SpinnerListModel(products) {
@Override
public Object getValue() {
return super.getValue();
}
};
// 创建自定渲染器显示产品名称
JSpinner spinner = new JSpinner(model);
// 自定义渲染器
JSpinner.ListEditor editor = new JSpinner.ListEditor(spinner) {
{
getTextField().setEditable(false);
}
};
frame.add(spinner);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
class Product {
String name;
double price;
Product(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return name + " - ¥" + price;
}
}
示例3:带事件监听的复杂示例
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
public class AdvancedListExample extends JFrame {
private JLabel statusLabel;
private JSpinner spinner;
public AdvancedListExample() {
setTitle("高级列表模型示例");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// 创建数据
String[] cities = {"北京", "上海", "广州", "深圳", "成都", "杭州"};
int[] populations = {2154, 2428, 1530, 1756, 1658, 1220}; // 单位:万
// 创建组合数据模型
Object[][] cityData = new Object[cities.length][2];
for (int i = 0; i < cities.length; i++) {
cityData[i] = new Object[]{cities[i], populations[i]};
}
// 创建列表模型
SpinnerListModel model = new SpinnerListModel(cityData);
// 创建 Spinner
spinner = new JSpinner(model);
spinner.setFont(new Font("微软雅黑", Font.PLAIN, 14));
// 添加变化监听
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
updateStatus();
}
});
// 创建标签
statusLabel = new JLabel("请选择城市");
statusLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
statusLabel.setHorizontalAlignment(JLabel.CENTER);
// 布局
JPanel centerPanel = new JPanel(new FlowLayout());
centerPanel.add(new JLabel("选择城市:"));
centerPanel.add(spinner);
add(centerPanel, BorderLayout.CENTER);
add(statusLabel, BorderLayout.SOUTH);
setSize(400, 200);
setLocationRelativeTo(null);
// 更新状态
updateStatus();
}
private void updateStatus() {
Object[] selectedData = (Object[]) spinner.getValue();
String city = (String) selectedData[0];
int population = (int) selectedData[1];
statusLabel.setText(String.format("已选择 %s,人口约 %d 万", city, population));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new AdvancedListExample().setVisible(true);
});
}
}
高级特性
动态修改列表
public class DynamicListExample {
public static void main(String[] args) {
// 使用 List 实现动态修改
java.util.List<String> dynamicList = new java.util.ArrayList<>();
dynamicList.add("选项A");
dynamicList.add("选项B");
dynamicList.add("选项C");
SpinnerListModel model = new SpinnerListModel(dynamicList);
JSpinner spinner = new JSpinner(model);
// 添加新选项
JButton addButton = new JButton("添加选项D");
addButton.addActionListener(e -> {
dynamicList.add("选项D");
// 重置模型
spinner.setModel(new SpinnerListModel(dynamicList));
});
}
}
循环与非循环模式
// 默认是循环模式(到达末尾后回到开头) SpinnerListModel model = new SpinnerListModel(items); // 可以通过设置实现非循环模式(实际 SpinnerListModel 不支持直接设置) // 需要自定义模型或监听状态
自定义渲染器
JSpinner spinner = new JSpinner(model);
JSpinner.ListEditor editor = new JSpinner.ListEditor(spinner);
// 自定义字体和颜色
JFormattedTextField textField = editor.getTextField();
textField.setFont(new Font("Arial", Font.BOLD, 18));
textField.setForeground(Color.BLUE);
textField.setBackground(Color.LIGHT_GRAY);
注意事项
- 类型安全:所有列表元素应该是相同类型或兼容类型
- 不可变列表:如果使用数组,数组内容可以修改,但数组长度固定
- 初始值:默认选中列表的第一个元素
- null 值:避免在列表中包含 null 值,会导致异常
- 线程安全:Swing 组件操作应在 EDT 线程中进行
常见问题解决
问题1:修改列表后 Spinner 不更新
// 解决方法:重新设置模型 spinner.setModel(new SpinnerListModel(updatedList));
问题2:自定义对象的显示
// 确保自定义类重写 toString() 方法
@Override
public String toString() {
return this.name + " - " + this.value;
}
问题3:值变化监听
spinner.addChangeListener(e -> {
Object value = spinner.getValue();
// 处理值变化
});
JSpinnerListModel 是创建有限选项选择器的理想方式,特别适合用于设置、配置、选择器等场景。