Java 添加&;删除自定义组件JTable的行
我正在一步一步地做 注意:我有更多自定义列,此代码用于演示海豚 现在,我想使用一个从Java 添加&;删除自定义组件JTable的行,java,swing,jtable,defaulttablemodel,Java,Swing,Jtable,Defaulttablemodel,我正在一步一步地做 注意:我有更多自定义列,此代码用于演示海豚 现在,我想使用一个从DefaultTableModel扩展的类来实现addrow和deleteow,该类用于填充自定义对象的JTable 这是我的代码: import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.table.*; public class LAF_TableCustom_AddDelRow { s
DefaultTableModel
扩展的类来实现addrow和deleteow,该类用于填充自定义对象的JTable
这是我的代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class LAF_TableCustom_AddDelRow {
static JFrame frame = new JFrame();
public JComponent makeUI() {
String[] hdrsObjects = {"PanelSpinnerRadioButton Class Column"};
Object[][] objectMatrix = new Object[3][1];
objectMatrix[0][0] = new PanelSpinnerRadioButtonData(false, 10, 40);
objectMatrix[1][0] = new PanelSpinnerRadioButtonData(true, 20, 40);
objectMatrix[2][0] = new PanelSpinnerRadioButtonData(false, 30, 40);
// JTable table = new JTable(new DefaultTableModel(objectMatrix, hdrsObjects)) {
JTable table = new JTable(new PSRBTableModel(objectMatrix, hdrsObjects)) {
@Override public void updateUI() {
super.updateUI();
setRowHeight(30);
TableColumn tc = getColumn("PanelSpinnerRadioButton Class Column");
tc.setCellRenderer(new PSRBTableCellRenderer());
tc.setCellEditor(new PSRBTableCellEditor());
}
};
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
JPanel pV = new JPanel();
pV.setLayout(new BoxLayout(pV, BoxLayout.PAGE_AXIS));
JButton bAddRow = new JButton("Add Row");
bAddRow.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent evt) {
((PSRBTableModel)table.getModel()).addRow(
new Object[] { new PanelSpinnerRadioButtonData(false, 10, 40) }
);
// ((DefaultTableModel)table.getModel()).addRow(
// new Object[] { new PanelSpinnerRadioButtonData(false, 10, 40) }
// );
}
});
pV.add(bAddRow);
pV.add(scrollPane);
return pV;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
frame.getContentPane().add(new LAF_TableCustom_AddDelRow().makeUI());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(320, 240);
frame.setVisible(true);
});
}
}
class PanelSpinnerRadioButtonData {
private boolean opt02 = false;
private Integer from = 0;
private Integer size = 1;
PanelSpinnerRadioButtonData() {
this(false, 5, 10);
}
PanelSpinnerRadioButtonData(boolean opt02, Integer from, Integer size) {
this.opt02 = opt02;
this.from = from;
this.size = size;
}
public boolean getOption() {
return opt02;
}
public Integer getFrom() {
return from;
}
public Integer getSize() {
return size;
}
}
class PanelSpinnerRadioButton extends JPanel {
public final JRadioButton jrbOption01 = new JRadioButton("01");
public final JRadioButton jrbOption02 = new JRadioButton("12");
public final JSpinner jspnValues = new JSpinner(new SpinnerNumberModel(5, 0, 10, 1));
public final JButton jbRemoveRow = new JButton("Del Row");
private final JPanel panel = new JPanel();
PanelSpinnerRadioButton() {
this(new PanelSpinnerRadioButtonData(false, 20, 40));
}
PanelSpinnerRadioButton(PanelSpinnerRadioButtonData data) {
super();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.add(jrbOption01);
panel.add(jrbOption02);
panel.add(jspnValues);
panel.add(jbRemoveRow);
jbRemoveRow.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
JTable table = (JTable)SwingUtilities.getAncestorOfClass(
JTable.class, (Component) e.getSource());
int row = table.getEditingRow();
table.getCellEditor().stopCellEditing();
// ((DefaultTableModel) table.getModel()).removeRow(row);
((PSRBTableModel) table.getModel()).removeRow(row);
}
});
ButtonGroup bg = new ButtonGroup();
bg.add(jrbOption01);
bg.add(jrbOption02);
((SpinnerNumberModel) jspnValues.getModel()).setMaximum(data.getSize());
setData(data);
init();
}
private void init() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0));
add(panel);
}
public void setData(PanelSpinnerRadioButtonData data) {
if (data.getOption()) {
jrbOption02.setSelected(true);
} else {
jrbOption01.setSelected(true);
}
((SpinnerNumberModel) jspnValues.getModel()).setValue(data.getFrom());
}
public PanelSpinnerRadioButtonData getData() {
return new PanelSpinnerRadioButtonData(
jrbOption02.isSelected(),
(Integer) ((SpinnerNumberModel) jspnValues.getModel()).getValue(),
(Integer) ((SpinnerNumberModel) jspnValues.getModel()).getMaximum());
}
}
class PSRBTableCellRenderer implements TableCellRenderer {
private final PanelSpinnerRadioButton renderer = new PanelSpinnerRadioButton();
@Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
renderer.setData((PanelSpinnerRadioButtonData) value);
}
return renderer;
}
}
class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private final PanelSpinnerRadioButton editor = new PanelSpinnerRadioButton();
@Override public Object getCellEditorValue() {
return editor.getData();
}
@Override public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
editor.setData((PanelSpinnerRadioButtonData) value);
}
return editor;
}
}
//class PSRBTableModel extends AbstractTableModel {
class PSRBTableModel extends DefaultTableModel {
private final Object[][] data;
private final Object[] columns;
public PSRBTableModel(Object[][] data, Object[] columns) {
this.data = data;
this.columns = columns;
}
@Override public Object getValueAt(int rowIndex, int columnIndex) {
if (data != null) {
if (data.length > 0) {
return data[rowIndex][columnIndex];
}
}
return null;
}
@Override public int getColumnCount() {
return ((columns == null) ? 0: columns.length);
}
@Override public int getRowCount() {
return ((data == null) ? 0: data.length);
}
@Override public Class getColumnClass(int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) {
return PanelSpinnerRadioButton.class;
}
return data[0][columnIndex].getClass();
}
}
return Object.class;
}
@Override public boolean isCellEditable(int rowIndex, int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) {
return true;
}
}
}
return true;
}
@Override public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
@Override public String getColumnName(int columnIndex) {
return (String)columns[columnIndex];
}
@Override public void removeRow(int row) {
fireTableRowsDeleted(row, row);
System.out.println("fireTableRowsDeleted(" + row + ", " + row + ");");
}
@Override public void addRow(Object[] rowData) {
super.addRow(rowData);
}
}
问题
当我按下Del Row
按钮时,该行没有被删除!
我得到了与行相关的打印消息:fireTableRowsDeleted(行,行)代码>I
当我按下添加行
时,我得到了这个异常
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3 > 0
at java.util.Vector.insertElementAt(Vector.java:598)
at javax.swing.table.DefaultTableModel.insertRow(DefaultTableModel.java:374)
at javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:350)
at javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:361)
at PSRBTableModel.addRow(LAF_TableCustom_AddDelRow.java:248)
at LAF_TableCustom_AddDelRow$2.actionPerformed(LAF_TableCustom_AddDelRow.java:45)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
如何使用自定义的DefaultTableModel
覆盖相应的方法来执行这些操作(removeRow、addRow)
这是行不通的
编辑
//Doesn't Work
@Override public void removeRow(int row) {
super.removeRow(row);
}
//Doesn't Work
@Override public void removeRow(int row) {
getDataVector().removeElementAt(row);
fireTableRowsDeleted(row, row);
}
//Doesn't Work (Not overriding the Method)
// @Override public void removeRow(int row) {
// getDataVector().removeElementAt(row);
// }
基本问题是,DefaultTableModel
已经由一个管理行/列数据的向量支持。但是您对它的扩展,实现了它自己的数据结构,使得向量
冗余
如果您花时间查看DefaultTabelModel
的源代码,您会发现addRow(Object[])
调用addRow(Vector)
,它使用getRowCount
,调用它的实现
/**
* Adds a row to the end of the model. The new row will contain
* <code>null</code> values unless <code>rowData</code> is specified.
* Notification of the row being added will be generated.
*
* @param rowData optional data of the row being added
*/
public void addRow(Vector rowData) {
insertRow(getRowCount(), rowData);
}
/**
* Adds a row to the end of the model. The new row will contain
* <code>null</code> values unless <code>rowData</code> is specified.
* Notification of the row being added will be generated.
*
* @param rowData optional data of the row being added
*/
public void addRow(Object[] rowData) {
addRow(convertToVector(rowData));
}
这意味着Vector
中没有任何内容,但您的代码表示有3行,这基本上触发了所有核心问题
你有一个选择。要么使用DefaultTableModel
并抛弃您自己的数据结构(data
和columns
),要么使用类似于AbstractTableModel
的东西,这将迫使您实现您自己的数据结构
最基本的建议可能是第一种,因为DefaultTableModel
应该能够提供您似乎需要的基本基本需求
对于一个非常基本的例子:
class PSRBTableModel extends DefaultTableModel {
public PSRBTableModel(Object[][] data, Object[] columns) {
super(data, columns);
}
@Override
public Class getColumnClass(int columnIndex) {
if (getRowCount() > 0) {
Object value = getValueAt(0, columnIndex);
if (value instanceof PanelSpinnerRadioButton) {
return PanelSpinnerRadioButton.class;
}
}
return Object.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return getColumnClass(columnIndex) == PanelSpinnerRadioButton.class;
}
}
基本问题是,DefaultTableModel
已经由一个管理行/列数据的向量支持。但是您对它的扩展,实现了它自己的数据结构,使得向量
冗余
如果您花时间查看DefaultTabelModel
的源代码,您会发现addRow(Object[])
调用addRow(Vector)
,它使用getRowCount
,调用它的实现
/**
* Adds a row to the end of the model. The new row will contain
* <code>null</code> values unless <code>rowData</code> is specified.
* Notification of the row being added will be generated.
*
* @param rowData optional data of the row being added
*/
public void addRow(Vector rowData) {
insertRow(getRowCount(), rowData);
}
/**
* Adds a row to the end of the model. The new row will contain
* <code>null</code> values unless <code>rowData</code> is specified.
* Notification of the row being added will be generated.
*
* @param rowData optional data of the row being added
*/
public void addRow(Object[] rowData) {
addRow(convertToVector(rowData));
}
这意味着Vector
中没有任何内容,但您的代码表示有3行,这基本上触发了所有核心问题
你有一个选择。要么使用DefaultTableModel
并抛弃您自己的数据结构(data
和columns
),要么使用类似于AbstractTableModel
的东西,这将迫使您实现您自己的数据结构
最基本的建议可能是第一种,因为DefaultTableModel
应该能够提供您似乎需要的基本基本需求
对于一个非常基本的例子:
class PSRBTableModel extends DefaultTableModel {
public PSRBTableModel(Object[][] data, Object[] columns) {
super(data, columns);
}
@Override
public Class getColumnClass(int columnIndex) {
if (getRowCount() > 0) {
Object value = getValueAt(0, columnIndex);
if (value instanceof PanelSpinnerRadioButton) {
return PanelSpinnerRadioButton.class;
}
}
return Object.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return getColumnClass(columnIndex) == PanelSpinnerRadioButton.class;
}
}
从您自己的代码开始:
编辑PSRBTableModel
类
private Object[][] data; //Can't be final, you are changing!!!
现在的方法是:
@Override
public void removeRow(int row) {
Object[][] newData = new Object[data.length - 1][data[0].length];
int rown = 0;
for (int row1 = 0; row1 <data.length; row1++) {
if (row1 != row) {
for (int col = 0; col < data[0].length; col++) {
newData[rown][col] = data[row1][col];
}
rown++;
}
}
data = newData;
}
@Override
public void addRow(Object[] rowData) {
Object[][] newData = new Object[data.length + 1][data[0].length];
for (int row = 0; row <data.length; row++) {
for (int col = 0; col < data[0].length; col++) {
newData[row][col] = data[row][col];
}
}
int maxCol = data[0].length < rowData.length?data[0].length:rowData.length;
for (int col = 0; col < maxCol; col++) {
newData[data.length][col] = rowData[col];
}
data = newData;
}
但是,如果您的PSRBTableModel
类是从DefaultTableModelclass
扩展而来的,请离开它们
class PSRBTableModel extends DefaultTableModel {
在您的LAF\u TableCustom\u AddDelRow
类中:
JButton bAddRow = new JButton("Add Row");
bAddRow.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent evt) {
((PSRBTableModel)table.getModel()).addRow(
new Object[] { new PanelSpinnerRadioButtonData(false, 10, 40) }
);
table.updateUI();
}
});
在面板SpinnerRadioButton
类中
jbRemoveRow.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
JTable table = (JTable)SwingUtilities.getAncestorOfClass(
JTable.class, (Component) e.getSource());
int row = table.getEditingRow();
table.getCellEditor().stopCellEditing();
((PSRBTableModel)table.getModel()).removeRow(row);
// table.updateUI();
}
});
从您自己的代码开始:
编辑PSRBTableModel
类
private Object[][] data; //Can't be final, you are changing!!!
现在的方法是:
@Override
public void removeRow(int row) {
Object[][] newData = new Object[data.length - 1][data[0].length];
int rown = 0;
for (int row1 = 0; row1 <data.length; row1++) {
if (row1 != row) {
for (int col = 0; col < data[0].length; col++) {
newData[rown][col] = data[row1][col];
}
rown++;
}
}
data = newData;
}
@Override
public void addRow(Object[] rowData) {
Object[][] newData = new Object[data.length + 1][data[0].length];
for (int row = 0; row <data.length; row++) {
for (int col = 0; col < data[0].length; col++) {
newData[row][col] = data[row][col];
}
}
int maxCol = data[0].length < rowData.length?data[0].length:rowData.length;
for (int col = 0; col < maxCol; col++) {
newData[data.length][col] = rowData[col];
}
data = newData;
}
但是,如果您的PSRBTableModel
类是从DefaultTableModelclass
扩展而来的,请离开它们
class PSRBTableModel extends DefaultTableModel {
在您的LAF\u TableCustom\u AddDelRow
类中:
JButton bAddRow = new JButton("Add Row");
bAddRow.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent evt) {
((PSRBTableModel)table.getModel()).addRow(
new Object[] { new PanelSpinnerRadioButtonData(false, 10, 40) }
);
table.updateUI();
}
});
在面板SpinnerRadioButton
类中
jbRemoveRow.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
JTable table = (JTable)SwingUtilities.getAncestorOfClass(
JTable.class, (Component) e.getSource());
int row = table.getEditingRow();
table.getCellEditor().stopCellEditing();
((PSRBTableModel)table.getModel()).removeRow(row);
// table.updateUI();
}
});
在调用fireTableRowsDeleted
之前,实际上需要从底层数据结构中删除行,为此,我建议使用某种列表
,而不是简单得多的数组。如果您想在模型中拥有自己的数据结构,那么您需要停止使用父类提供的功能,或者利用父类已经提供的支持class@MadProgrammer我编辑了我的问题,添加了其他尝试…在您调用fireTableRowsDeleted
之前,实际上,您需要从底层数据结构中删除行,为此,我建议使用某种类型的列表
,而不是数组,这要简单得多。如果您想在模型中拥有自己的数据结构,那么您需要停止使用父类提供的功能,或者利用父类已经提供的支持class@MadProgrammer我编辑了我的问题,添加了另一个尝试…感谢您的时间,在您的代码中添加行,我需要对我的getValueAt
,getColumnCount
,getRowCount
,setValueAt
,getColumnName
,进行注释,但是Del Row
,仍然不起作用。请查看,不要让我操作控件、Jspinner、JRadioButtons。感谢您抽出时间,让您的代码添加Row
起作用,我需要对我的getValueAt
,getColumnCount
,getRowCount
,setValueAt
,getColumnName
,进行注释,但是Del Row
,仍然不起作用。请查看,不要让我操作控件、Jspinner、JRadioButtons。