JTable引发AWT事件队列0数组越界异常求助
JPanel实现日历JTable时的数组越界异常解决
问题核心原因
你遇到的ArrayIndexOutOfBoundsException本质是JTable的行数据结构完全搞反了。JTable构造方法JTable(Object[][] rowData, Object[] columnNames)要求第一个参数是行的集合:每个子数组代表一行的所有列元素;但你当前把「每一列的所有行元素」当成了行数据传入,导致JTable渲染时访问不存在的列索引,触发越界异常。
举个例子:
- 你当前的
dates数组结构:[[周一的所有面板], [周二的所有面板], ..., [周日的所有面板]] - JTable需要的正确结构:
[[第1周周一, 第1周周二, ..., 第1周周日], [第2周周一, ...], ...]
修正方案与代码
下面是调整后的完整代码,同时优化了冗余逻辑,确保日历布局正确:
import javax.swing.*; import java.util.ArrayList; import java.util.GregorianCalendar; import java.util.List; public class Calendar { JTable calendar; GregorianCalendar cal; JPanel[][] dates; public Calendar() { cal = new GregorianCalendar(); cal.set(2024, 3, 1); // 注意:GregorianCalendar的月份从0开始,3代表四月 String[] days = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; // 初始化每周各天的面板列表 List<JPanel> monList = new ArrayList<>(); List<JPanel> tueList = new ArrayList<>(); List<JPanel> wedList = new ArrayList<>(); List<JPanel> thurList = new ArrayList<>(); List<JPanel> friList = new ArrayList<>(); List<JPanel> satList = new ArrayList<>(); List<JPanel> sunList = new ArrayList<>(); // 填充当月各天的面板 while (cal.get(GregorianCalendar.MONTH) == 3) { int dayOfWeek = cal.get(GregorianCalendar.DAY_OF_WEEK); JPanel dayPanel = new JPanel(); dayPanel.add(new JLabel(String.valueOf(cal.get(GregorianCalendar.DATE)))); // 根据星期几添加到对应列表 switch (dayOfWeek) { case GregorianCalendar.MONDAY: monList.add(dayPanel); break; case GregorianCalendar.TUESDAY: tueList.add(dayPanel); break; case GregorianCalendar.WEDNESDAY: wedList.add(dayPanel); break; case GregorianCalendar.THURSDAY: thurList.add(dayPanel); break; case GregorianCalendar.FRIDAY: friList.add(dayPanel); break; case GregorianCalendar.SATURDAY: satList.add(dayPanel); break; case GregorianCalendar.SUNDAY: sunList.add(dayPanel); break; } // 处理当月第一天不是周一的情况,在对应星期列表头部补空面板 if (cal.get(GregorianCalendar.DATE) == 1) { for (int i = 0; i < dayOfWeek - 2; i++) { switch (i) { case 0: monList.add(0, new JPanel()); break; case 1: tueList.add(0, new JPanel()); break; case 2: wedList.add(0, new JPanel()); break; case 3: thurList.add(0, new JPanel()); break; case 4: friList.add(0, new JPanel()); break; case 5: satList.add(0, new JPanel()); break; } } } cal.add(GregorianCalendar.DATE, 1); } // 统一所有列表的长度,补全空面板 int maxRowCount = Math.max(Math.max(monList.size(), tueList.size()), Math.max(Math.max(wedList.size(), thurList.size()), Math.max(friList.size(), Math.max(satList.size(), sunList.size())))); while (monList.size() < maxRowCount) monList.add(new JPanel()); while (tueList.size() < maxRowCount) tueList.add(new JPanel()); while (wedList.size() < maxRowCount) wedList.add(new JPanel()); while (thurList.size() < maxRowCount) thurList.add(new JPanel()); while (friList.size() < maxRowCount) friList.add(new JPanel()); while (satList.size() < maxRowCount) satList.add(new JPanel()); while (sunList.size() < maxRowCount) sunList.add(new JPanel()); // 构造JTable需要的行优先数据结构 dates = new JPanel[maxRowCount][7]; for (int row = 0; row < maxRowCount; row++) { dates[row][0] = monList.get(row); dates[row][1] = tueList.get(row); dates[row][2] = wedList.get(row); dates[row][3] = thurList.get(row); dates[row][4] = friList.get(row); dates[row][5] = satList.get(row); dates[row][6] = sunList.get(row); } calendar = new JTable(dates, days); } // 测试用主方法 public static void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame("Calendar"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(new Calendar().calendar)); frame.pack(); frame.setVisible(true); }); } }
关键修正点
- 调整JTable数据结构:将原来的「列优先」数组改为「行优先」,确保每个子数组对应一行的7列元素,完全匹配列名数组的长度
- 简化日期填充逻辑:去掉switch里的冗余判断,直接使用
GregorianCalendar的常量增强代码可读性 - 正确处理月初补位:当月第一天不是周一的时候,在对应星期的列表头部添加空面板,保证日历布局对齐
- 统一列表长度:使用循环补全空面板,替代原来的链式判断,逻辑更清晰易维护
内容的提问来源于stack exchange,提问作者Noah Gaston
相关产品推荐
相关产品推荐

