You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
        });
    }
}

关键修正点

  1. 调整JTable数据结构:将原来的「列优先」数组改为「行优先」,确保每个子数组对应一行的7列元素,完全匹配列名数组的长度
  2. 简化日期填充逻辑:去掉switch里的冗余判断,直接使用GregorianCalendar的常量增强代码可读性
  3. 正确处理月初补位:当月第一天不是周一的时候,在对应星期的列表头部添加空面板,保证日历布局对齐
  4. 统一列表长度:使用循环补全空面板,替代原来的链式判断,逻辑更清晰易维护

内容的提问来源于stack exchange,提问作者Noah Gaston

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:39:50