java - 使用 jbutton 从 jtable 中删除一行

标签 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();
            }
            });

    }
}

}

最佳答案

因此,稍微查看一下堆栈跟踪可以让我们更好地了解正在发生的事情......

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另一种方法

关于java - 使用 jbutton 从 jtable 中删除一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51841524/

相关文章:

java - 限制 html JLabel 中的行数

java - 使用 java servlet 的 http 流式传输

java - 安卓 Java : HttpURLConnection

java - 在生产代码中,无法验证请求参数或格式时的日志级别是多少

java - JPanel 忘记了它的位置

Java Swing JScrollPane 包含更多不滚动的 Pane ?

java - 使用java swing表更新MySQL数据库值

java - JTable 标题仍未显示

java - 更改 JTable 的外观

java - 使用正则表达式进行流模式匹配