使用 jbutton 从 jtable 中删除一行
remove a row from jtable with jbutton
我有一个带有 JButton 的 JTable,就像这样。
first pic
如果我点击“+”按钮,table是这样的。
second pic
那我点击第二行的“-”按钮就可以了
现在 table 只有一行是通过“+”按钮添加的。
所以问题是,我点击了行上的“-”按钮,它抛出了下面的异常:
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 另一种方法
我有一个带有 JButton 的 JTable,就像这样。 first pic
如果我点击“+”按钮,table是这样的。 second pic
那我点击第二行的“-”按钮就可以了
现在 table 只有一行是通过“+”按钮添加的。
所以问题是,我点击了行上的“-”按钮,它抛出了下面的异常:
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 另一种方法