【问题标题】:Clearing a JTable throws an arrayIndexOutOfBounds Issue清除 JTable 会引发 arrayIndexOutOfBounds 问题
【发布时间】:2015-09-05 11:36:54
【问题描述】:

所以我有一个使用 JTable 的程序。每次我想删除一行并刷新表格时,都会引发以下错误。

 Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1

我曾多次看到与此问题类似的问题:

jTable populating and refreshing ArrayIndexOutOfBoundsException

Refreshing JTable in Swing Gives Exception

ArrayIndexOutOfBoundsException when trying to empty a JTable

还有一些其他的。

但我似乎无法破译是什么原因导致我出现这种情况。我的程序所做的是在启动时使用数据库中的数据填充表。我没有在表格中插入对象;只是直接来自数据库的字符串值。我的屏幕是这样的:

选择一行会将其值放入框架顶部的文本框中。理想情况下,如果我单击删除 Office_ID 字段中的 ID,然后将用于从我的数据库中删除一行,并刷新表以删除该行。删除工作正常,但我的程序没有刷新表,而是抛出了数组索引越界错误。

建表的代码在这里:

    private DefaultTableModel estateModel;
private JTextField IDField, addressField, suburbField, postcodeField, stateField, phoneField, faxField; 
private JTable estateTable;
private final JPanel containerPanel;
private JButton add, edit, view, delete, search, close;

public EstateScreen()
{
    containerPanel = new JPanel();
    containerPanel.setLayout(new BoxLayout(containerPanel, BoxLayout.Y_AXIS));
    addGridToPanel();
    addTableToPanel();
    addButtonsToPanel();
}


private void addTableToPanel()
{
    JPanel tablePane = new JPanel(new BorderLayout(2,2));
    String[] colNames = {"Office ID", "Address", "Suburb", "Postcode", "State", "Phone Number", "Fax Number"};
    estateModel = new DefaultTableModel()
    {
        @Override
        public boolean isCellEditable(int row, int column)
        {
            return false;
        }
    };
    estateModel.setColumnIdentifiers(colNames);
    estateTable = new JTable(estateModel);
    JScrollPane scroll = new JScrollPane(estateTable);
    tablePane.add(scroll);

    estateTable.getSelectionModel().addListSelectionListener(new ListSelectionListener()
    {
        @Override
        public void valueChanged(ListSelectionEvent event)
        {
            IDField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),0).toString());
            addressField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),1).toString());
            suburbField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),2).toString());
            postcodeField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),3).toString());
            stateField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),4).toString());
            phoneField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),5).toString());
            faxField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),6).toString());
        }
    });

    containerPanel.add(tablePane);
}

我的清表方法:

    public void clearTable()
{
    estateModel.setRowCount(0);
    /*
   estateModel.removeTableModelListener(estateTable);
   while(estateModel.getRowCount() > 0)
   {
       estateModel.removeRow(0);
   }
   estateModel.addTableModelListener(estateTable);*/
}

以及删除按钮的actionListener:

        gui.getEstateScreen().getDelete().addActionListener(new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            if(office.deleteByID(connB, gui.getEstateScreen().getID(), "office_id"))
            {
                gui.getEstateScreen().clearTable();
                populateEmployerScreen();
            }
            else
            {
                gui.getEstateScreen().outputAddError("Could not delete this office");
            }
        }
    });

以及用于良好测量的填充屏幕方法:

    private void populateEmployerScreen()
{
    try
    {
        ResultSet rs = office.getAllData(connB);
        while(rs.next())
        {
            String[] data = new String[7];
            data[0] = Integer.toString(rs.getInt("OFFICE_ID"));
            data[1] = rs.getString("ADDRESS");
            data[2] = rs.getString("SUBURB");
            data[3] = Integer.toString(rs.getInt("POSTCODE"));
            data[4] = rs.getString("STATE");
            data[5] = rs.getString("PHONE_NUMBER");
            data[6] = rs.getString("FAX_NUMBER");

            gui.getEstateScreen().getModel().addRow(data);
        }

    }
    catch(SQLException s)
    {

    }

}

最后一点。有趣的是,如果我在程序开始时没有选择任何行时调用 clear table 方法,它就可以正常工作。当我单击其中一行时,它开始抛出数组索引越界错误。对此我唯一能想到的是,当它被选中时,它以某种方式无法清除一行。

谁能帮我解决这个问题?

堆栈跟踪:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.Vector.elementData(Vector.java:730)
at java.util.Vector.elementAt(Vector.java:473)
at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:649)
at javax.swing.JTable.getValueAt(JTable.java:2717)
at view.main.EstateScreen$2.valueChanged(EstateScreen.java:95)
at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:184)
at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:164)
at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:211)
at javax.swing.DefaultListSelectionModel.removeIndexInterval(DefaultListSelectionModel.java:677)
at javax.swing.JTable.tableRowsDeleted(JTable.java:4509)
at javax.swing.JTable.tableChanged(JTable.java:4412)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at javax.swing.table.AbstractTableModel.fireTableRowsDeleted(AbstractTableModel.java:261)
at javax.swing.table.DefaultTableModel.setNumRows(DefaultTableModel.java:321)
at javax.swing.table.DefaultTableModel.setRowCount(DefaultTableModel.java:339)
at view.main.EstateScreen.clearTable(EstateScreen.java:158)
at controller.RealEstateAgency$4.actionPerformed(RealEstateAgency.java:154)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6516)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6281)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:740)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:699)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:713)
at java.awt.EventQueue$4.run(EventQueue.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:710)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

【问题讨论】:

  • 可以添加堆栈跟踪吗?
  • 问题可能出在您的选择监听器上,您没有检查 selectedRow 方法是否返回 -1。
  • 你读过堆栈跟踪吗?这根本不是 ArrayIndexOutOfBoundsException,而是从 EstateScreen.getID() 第 133 行抛出的 NumberFormatException。
  • 很明显,您正在尝试使用 EstateScreen.getID 中的 Integer.parseInt 函数将空字符串解析为整数,就像 JB Nizet 提到的那样
  • 抱歉,我发布了错误的堆栈跟踪。这是在我玩弄我的代码时生成的。 KDM 似乎是正确的;这与我的选择听众有关

标签: java swing


【解决方案1】:

最好遵循框架/语言的标准习语。不要添加和删除侦听器,而是为您的 valueChanged 方法添加一个守卫。

public void valueChanged(ListSelectionEvent event) {
    int selectedRow = estateTable.getSelectedRow();
    if(selectedRow == -1) {
        // Most probably you should be clearing the text fields
        // here. At the least do a return
        return;
    }
    // Other code
}

【讨论】:

    【解决方案2】:

    非常感谢 KDM 指出问题出在我的 ListSelectionListener 上。

    通过在清除表之前删除侦听器然后再次添加它来解决我的问题。

    public void clearTable()
    {
        estateTable.getSelectionModel().removeListSelectionListener(listener);
        estateModel.setRowCount(0);
        estateTable.getSelectionModel().addListSelectionListener(listener);
    }
    

    【讨论】:

      【解决方案3】:

      有点晚了,但是在ListSelectionListener中设置文本框的文本之前尝试添加下面的代码行

      if (!e.getValueIsAdjusting() && estateTable.getSelectedRow() != -1)
      

      【讨论】:

        猜你喜欢
        • 2015-01-22
        • 2016-09-08
        • 2011-11-24
        • 1970-01-01
        • 2021-01-10
        • 2012-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多