我有一个像这样带有 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
的调用,传入编辑 row
、column
和getCellEditorValue
的结果,但是,由于这种情况发生在 ActionListener
从 TableModel
中删除该行之后,它会中断,因为该行, 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/