清除JTable会抛出arrayIndexOutOfBounds问题

时间:2015-09-05 11:36:54

标签: java swing

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

SELECT t1.FIRST_NAME
FROM EMPLOYEES t1
LEFT JOIN EMPLOYEES t2 ON t1.EMPLOYEE_ID = t2.MANAGER_ID
WHERE t2.MANAGER_ID IS NULL

我已经看过几次与此问题相似的问题:

jTable populating and refreshing ArrayIndexOutOfBoundsException

Refreshing JTable in Swing Gives Exception

ArrayIndexOutOfBoundsException when trying to empty a JTable

和其他一些人。

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

enter image description here

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

构建表的代码如下:

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

我清算桌子的方法:

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

和删除按钮的actionListener:

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

和填充Screen方法以及良好的衡量标准:

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

最后一点。有趣的是,如果我在程序开始时调用clear table方法时没有选择任何行,它可以正常工作。我点击其中一行但它开始抛出数组索引超出边界错误的那一刻。我能想到的唯一一件事就是它在选择时清除一行时会出现问题。

任何人都可以帮我吗?

堆栈追踪:

    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)
    {

    }

}

3 个答案:

答案 0 :(得分:2)

最好遵循框架/语言的标准习语。不是添加和删除侦听器,而是为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
}

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

有点晚了,但在设置ListSelectionListener

中的文本框文本之前,请尝试添加下面的代码行
if (!e.getValueIsAdjusting() && estateTable.getSelectedRow() != -1)