我一步一步地做......
Changing LookAndFeel of JTable of Custom Component
注意:我有更多自定义列,此代码用于示范海豚。
现在,我想使用从DefaultTableModel
扩展的类来实现添加行和删除行,对于填充了自定义对象的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(ROW, ROW);
我
当我按下Add Row
时,我得到了这个例外......
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)
如何执行这些操作(removeRow,addRow),使用我的自定义DefaultTableModel
覆盖相应的方法?
此answer无效
编辑
//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);
// }
答案 0 :(得分:2)
基本问题是,DefaultTableModel
已由Vector
支持,Vector
管理行/列数据。但是你的扩展,实现了它自己的数据结构,使DefaultTabelModel
变得多余。
如果您花时间查看addRow(Object[])
的源代码,您会发现使用addRow(Vector)
的{{1}}个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;
}
}
答案 1 :(得分:1)
从您自己的代码开始:
编辑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
课程从AbstractTableModel
移除@Override
代码
class PSRBTableModel extends AbstractTableModel {
但是,如果您的PSRBTableModel
课程从[{1}}延长,请离开他们!
DefaultTableModelclass
在class PSRBTableModel extends DefaultTableModel {
课程中:
LAF_TableCustom_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();
}
});
班级
PanelSpinnerRadioButton