如何修复Java Swing中ComboBox的数据填充与联动问题?
球员与赛事管理程序的ComboBox数据加载问题修复
问题描述
我正在为足球俱乐部开发一款球员与赛事管理程序,采用SQLite数据库与Java Swing框架实现,程序包含两个ComboBox:一个用于选择类型(Spieler/Events),另一个用于显示对应球员或赛事名称。预期功能为切换类型ComboBox的选中项时,重新从数据库加载对应数据到第二个ComboBox中。
但当前代码存在两个问题:
- 第二个ComboBox的数据填充显示异常;
- 将
type的声明移至配置函数时,会抛出空指针异常(Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "selected" is null)。
用户提供的代码:
import javax.swing.*; import java.awt.*; import java.sql.*; import java.text.MessageFormat; public class MainWindow extends JFrame { private JPanel window; private JComboBox<String> comboBox2; private JButton deleteButton; private JComboBox<String> type = new JComboBox<>(new String[] {"Spieler", "Events"}); private JButton addButton; private JButton changeButton; String selected = (String) type.getSelectedItem(); Util util = new Util(); MainWindow() throws SQLException{ setConfigurations(); reloadSelection(selected); type.addActionListener(e -> { try {reloadSelection((selected));} catch (SQLException ex) {throw new RuntimeException(ex);} }); addButton.addActionListener(e -> System.out.println("not yet implemented")); deleteButton.addActionListener(e -> System.out.println("not yet implemented")); changeButton.addActionListener(e -> System.out.println("not yet implemented")); } private void reloadSelection(String selected) throws SQLException { Connection c = util.getConnection(); Statement stmt = c.createStatement(); String[] arr = new String[0]; String query; System.out.println(selected); if(selected.equals("Spieler")) { query = "SELECT firstName, lastName FROM Players;"; ResultSet rs = stmt.executeQuery(query); while(rs.next()) { String name = rs.getString("firstName") + rs.getString("lastName"); arr = name.split("\n"); } } /*else if(selected.equals("Events")) { query = "SELECT eventName FROM Events;"; } */ comboBox2.setModel(new DefaultComboBoxModel<>(arr)); util.closeConnection(c); } private void setConfigurations() { setContentPane(window); setName("LineUp"); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setSize(350, 175); setMaximumSize(new Dimension(350, 175)); setMinimumSize(new Dimension(350, 175)); } }
问题分析与修复方案
1. 数据填充异常修复
问题原因
- 遍历数据库结果集时,每次用
arr = name.split("\n");覆盖数组,最终仅保留最后一条数据; - 球员姓名拼接时无空格分隔,导致名字连在一起;
- Events分支被注释,无法加载赛事数据。
修复代码
改用List<String>动态存储数据,避免覆盖,同时完善赛事数据加载逻辑:
import java.util.ArrayList; import java.util.List; private void reloadSelection(String selected) throws SQLException { Connection c = util.getConnection(); Statement stmt = c.createStatement(); List<String> dataList = new ArrayList<>(); String query; // 常量在前调用equals,避免空指针 if("Spieler".equals(selected)) { query = "SELECT firstName, lastName FROM Players;"; ResultSet rs = stmt.executeQuery(query); while(rs.next()) { // 姓名间添加空格分隔 String name = rs.getString("firstName") + " " + rs.getString("lastName"); dataList.add(name); } } else if("Events".equals(selected)) { query = "SELECT eventName FROM Events;"; ResultSet rs = stmt.executeQuery(query); while(rs.next()) { dataList.add(rs.getString("eventName")); } } // 将List转为数组设置到ComboBox comboBox2.setModel(new DefaultComboBoxModel<>(dataList.toArray(new String[0]))); util.closeConnection(c); }
2. 空指针异常修复
问题原因
- 类初始化阶段赋值
selected,若type在setConfigurations中才初始化,此时type.getSelectedItem()返回null,后续调用equals会触发空指针; - 监听事件未实时获取最新选中项,始终使用初始化时的
selected值。
修复步骤
- 移除类成员变量
selected,每次调用方法时实时从type获取选中项; - 若将
type移至setConfigurations,确保初始化后再使用; - 修改监听事件逻辑:
// 移除类成员变量String selected = ... MainWindow() throws SQLException{ setConfigurations(); // 初始化时获取当前选中项 reloadSelection((String) type.getSelectedItem()); type.addActionListener(e -> { try { // 实时获取最新选中的类型 reloadSelection((String) type.getSelectedItem()); } catch (SQLException ex) { throw new RuntimeException(ex); } }); // 其他按钮监听逻辑保持不变 } // 若将type移至setConfigurations,修改该方法: private void setConfigurations() { // 先初始化type type = new JComboBox<>(new String[] {"Spieler", "Events"}); setContentPane(window); setName("LineUp"); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setSize(350, 175); setMaximumSize(new Dimension(350, 175)); setMinimumSize(new Dimension(350, 175)); }
额外优化建议
- 使用
PreparedStatement替代Statement,规避SQL注入风险; - 采用try-with-resources语法自动关闭数据库资源(Connection、Statement、ResultSet);
- 为ComboBox添加默认提示文本,比如"请选择类型...";
- 处理空结果集场景,避免ComboBox无内容显示。
内容的提问来源于stack exchange,提问作者Paval1s
相关产品推荐
相关产品推荐

