用jbutton从jtable中删除一行

时间:2018-08-14 12:32:53

标签: java swing jtable

我有一个带有JButton的JTable,就像这样。 first pic

如果单击“ +”按钮,则表格如下所示。 second pic

然后,如果我单击第二行上的“-”按钮,就可以了。

现在该表只有一行是通过“ +”按钮添加的。

所以问题是,我单击行上的“-”按钮,它在下面抛出异常:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 1
at java.util.Vector.elementAt(Vector.java:477)
at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:664)

发生了什么事?

这是我的代码:

public class TableDeleteButtonEditor extends AbstractCellEditor implements TableCellEditor{

/**
 * 
 */
private static final long serialVersionUID = 1L;
JButton button;
String label;
boolean isPushed;
Vector<Vector<String>> vPartsTypeData;

DefaultTableModel dtm;
JTable partsTypeValueTable;

public TableDeleteButtonEditor(Vector<Vector<String>> vPartsTypeData, DefaultTableModel dtm, JTable partsTypeValueTable) {

    // TODO Auto-generated constructor stub
    //this.setClickCountToStart(1);
    this.vPartsTypeData = vPartsTypeData;
    this.dtm = dtm;
    this.partsTypeValueTable = partsTypeValueTable;
    this.vPartsTypeData = vPartsTypeData;
    button = new JButton();
    int selectedRow = partsTypeValueTable.getSelectedRow();
    System.out.println("selectedRow:"+selectedRow);
    System.out.println("Count:"+vPartsTypeData.size());
    button.addActionListener(new deleteButtonListener());
}

public Component getTableCellEditorComponent(final JTable table, Object value,  boolean isSelected,int row, int column) {
    if (isSelected) {
        button.setFont(new Font("Arial",Font.PLAIN,30));
        button.setForeground(table.getSelectionForeground());  
        button.setBackground(table.getSelectionBackground());  
    } else {
        button.setFont(new Font("Arial",Font.PLAIN,30));
        button.setForeground(table.getForeground());  
        button.setBackground(table.getBackground());  
    }  
    label = (value == null) ? "" : value.toString();  
    button.setText(label);
    isPushed = true;  
    return button;  
}  

public Object getCellEditorValue() {  
    if (isPushed) {

    }  
    isPushed = false;  
    return new String(label);  
}  

public boolean stopCellEditing() {  
    isPushed = false;
    return super.stopCellEditing();  
}  

public class deleteButtonListener implements ActionListener
{
    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        System.out.println("-----");
        int selectedRow = partsTypeValueTable.getSelectedRow();
        //System.out.println("selectedRow:"+selectedRow);
        //System.out.println("Count:"+vPartsTypeData.size());
        dtm.removeRow(selectedRow-1);

        //vPartsTypeData.remove(partsTypeValueTable.getSelectedRow());
        System.out.println("tableCount:"+partsTypeValueTable.getRowCount());
        //dtm.fireTableChanged(null);
        partsTypeValueTable.setModel(dtm);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                partsTypeValueTable.repaint();
                partsTypeValueTable.validate();
                partsTypeValueTable.updateUI();
                dtm.fireTableDataChanged();
            }
            });

    }
}

}

1 个答案:

答案 0 :(得分:1)

因此,稍微看一下堆栈跟踪就可以使我们更好地了解发生了什么...

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 1
    at java.util.Vector.elementAt(Vector.java:477)
    at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:664)
    at javax.swing.JTable.setValueAt(JTable.java:2741)
    at javax.swing.JTable.editingStopped(JTable.java:4723)
    at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:141)
    at javax.swing.AbstractCellEditor.stopCellEditing(AbstractCellEditor.java:85)

因此,基本上stopCellEditing触发了对setValueAt的调用,传递了编辑rowcolumngetCellEditorValue的结果,但是,由于这种情况发生在ActionListenerTableModel删除行之后,它中断了,因为setValueAt试图更新的行已经不存在了(或更糟的是,另一行合在一起了) )。

TableCellEditor并不负责修改TableModel,相反,它应该向TableModel报告一个状态值,它可以用来决定其内容。应该做。

编辑器的简化版可能看起来像...

public class TableDeleteButtonEditor extends AbstractCellEditor implements TableCellEditor {

    /**
     *
     */
    private static final long serialVersionUID = 1L;
    JButton button;
    boolean isPushed;

    public TableDeleteButtonEditor() {
        button = new JButton();
        button.addActionListener(new DeleteButtonListener());
    }

    public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, int row, int column) {
        if (isSelected) {
            button.setFont(new Font("Arial", Font.PLAIN, 30));
            button.setForeground(table.getSelectionForeground());
            button.setBackground(table.getSelectionBackground());
        } else {
            button.setFont(new Font("Arial", Font.PLAIN, 30));
            button.setForeground(table.getForeground());
            button.setBackground(table.getBackground());
        }
        button.setText((value == null) ? "" : value.toString());
        isPushed = false;
        return button;
    }

    public Object getCellEditorValue() {
        return isPushed;
    }

    public class DeleteButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            isPushed = true;
            stopCellEditing();
        }
    }
}

编辑器的核心功能只是围绕isPushed值的状态。

TableModel现在需要在调用setValueAt时检查该值并对其进行响应

@Override
public void setValueAt(Object aValue, int row, int column) {
    if (column == 0 && (aValue instanceof Boolean)) {
        boolean pushed = (boolean) aValue;
        if (pushed) {
            removeRow(row);
        }
    }
}                   

中提琴,现在行被删除了,大家都很开心。

可运行的示例...

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                DefaultTableModel model = new DefaultTableModel(new String[]{"A"}, 0) {
                    @Override
                    public void setValueAt(Object aValue, int row, int column) {
                        if (column == 0 && (aValue instanceof Boolean)) {
                            boolean pushed = (boolean) aValue;
                            if (pushed) {
                                removeRow(row);
                            }
                        }
                    }
                };
                model.addRow(new Object[]{"-"});
                model.addRow(new Object[]{"-"});
                JTable table = new JTable(model);
                TableColumn column = table.getColumnModel().getColumn(0);
                column.setCellEditor(new TableDeleteButtonEditor());

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TableDeleteButtonEditor extends AbstractCellEditor implements TableCellEditor {

        /**
         *
         */
        private static final long serialVersionUID = 1L;
        JButton button;
        boolean isPushed;
        JTable partsTypeValueTable;

        public TableDeleteButtonEditor() {
            button = new JButton();
            button.addActionListener(new DeleteButtonListener());
        }

        public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, int row, int column) {
            partsTypeValueTable = table;
            if (isSelected) {
                button.setFont(new Font("Arial", Font.PLAIN, 30));
                button.setForeground(table.getSelectionForeground());
                button.setBackground(table.getSelectionBackground());
            } else {
                button.setFont(new Font("Arial", Font.PLAIN, 30));
                button.setForeground(table.getForeground());
                button.setBackground(table.getBackground());
            }
            button.setText((value == null) ? "" : value.toString());
            isPushed = false;
            return button;
        }

        public Object getCellEditorValue() {
            return isPushed;
        }

        public class DeleteButtonListener implements ActionListener {

            @Override
            public void actionPerformed(ActionEvent e) {
                isPushed = true;
                stopCellEditing();
            }
        }
    }
}

就像我说的那样,我不喜欢这种方法,这是个人的事情,但是作为用户,我发现它令人沮丧,并且更喜欢更多like this for example

但是,您可能还希望了解Table Button Column的另一种方法