本文目录导读:

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 是创建有限选项选择器的理想方式,特别适合用于设置、配置、选择器等场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播