java 使用自定义 TableModel 使 isCellEditable 在按钮单击时为特定行设置为 true
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12405605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using custom TableModel make isCellEditable true for a particular row on button click
提问by Amarnath
I have a table like above. Initially all the cells except button column are not editable. I have created the table using custom TableModel
. My isCellEditable
in custom TableModel
looks like this:
我有一张像上面一样的桌子。最初,除按钮列之外的所有单元格都不可编辑。我已经使用 custom 创建了表格TableModel
。我isCellEditable
的自定义TableModel
看起来像这样:
public boolean isCellEditable(int rowIndex, int columnIndex) {
//System.out.println("isCellEditable: " + rowIndex + " " + columnIndex);
if(getColumnClass(columnIndex) == JButton.class)
return true;
else
return false;
}
But when I click on the Edit button of each row a JDialog
will pop up with that row (by constructing a JTable
in this dialog with only one row.) I can update the cell values in this JDialog's table. and then update them in the respective cells of that row.
但是,当我单击每一行的“编辑”按钮时,JDialog
将弹出该行(通过JTable
在此对话框中仅构造一行)。我可以更新此 JDialog 表中的单元格值。然后在该行的相应单元格中更新它们。
I am successfully able to update the main table's row after updating here, only if my isCellEditable
return true. But this should not happen. Only when I click then I should be able to change isCellEditable
of the row as Editable and update and then make it uneditable.
仅当我isCellEditable
返回 true 时,我才能在此处更新后成功更新主表的行。但这不应该发生。只有当我点击然后我才应该能够isCellEditable
将行更改为可编辑并更新,然后使其不可编辑。
I have seen the following postbut was unable to implement it.
我看过以下帖子,但无法实施。
采纳答案by kleopatra
Fleshing out my comment to the question:
充实我对这个问题的评论:
there's no need to tweak the editability of the full model: create another model populated by the filtered (column-wise) row of the original, make that other editable and on commit let it write back the changed values to the original
无需调整完整模型的可编辑性:创建另一个由原始模型的过滤(按列)行填充的模型,使其他模型可编辑,并在提交时让它将更改后的值写回原始模型
with a bit of code:
用一点代码:
public static class ButtonDialogEditor extends AbstractCellEditor
implements TableCellEditor {
// the columns to present for editing, in model coordinates
public final int lastColumn;
public final int firstColumn;
// the row to present for editing, in model coordinates
private int row;
private DefaultTableModel model;
private JDialog dialog;
private boolean committed;
private JButton editingComponent;
public ButtonDialogEditor(int firstColumn, int lastColumn) {
this.firstColumn = firstColumn;
this.lastColumn = lastColumn;
model = new DefaultTableModel(1, lastColumn - firstColumn + 1);
JTable table = new JTable(model);
table.putClientProperty("terminateEditOnFocusLost",true);
dialog = new JDialog();
dialog.setModal(true);
dialog.add(new JScrollPane(table));
dialog.add(new JButton(createOkAction()), BorderLayout.SOUTH);
dialog.pack();
editingComponent = new JButton(createShowDialogAction());
}
/**
* Returns the cell value at column. Note that column
* is in the model coordinate system of the source model.
*/
public Object getValueAt(int column) {
return model.getValueAt(0, column - firstColumn);
}
/**
* Returns the row index of the edited row in
* model coordinates of the source table.
*/
public int getModelRow() {
return row;
}
/**
* Creates and returns the action used for
* the editing component button.
*
* Implemented to show the modal dialog and fire
* editingSotpped/canceled depending on the committed
* flag
*/
private Action createShowDialogAction() {
Action action = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
// reset committed
committed = false;
dialog.setVisible(true);
if (committed) {
fireEditingStopped();
} else {
fireEditingCanceled();
}
}
};
return action;
}
/**
* Creates and returns the action used for the dialog's
* OK button.
*
* Implemented to hide the dialog and set the
* committed flag to true.
*/
private Action createOkAction() {
Action action = new AbstractAction("OK") {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
committed = true;
}
};
return action;
}
@Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
editingComponent.setText(value != null ? value.toString() : "");
prepareDialog(table, row);
return editingComponent;
}
/**
* Update internal state to the row to edit.
*/
private void prepareDialog(JTable table, int row) {
this.row = table.convertRowIndexToModel(row);
for (int i = firstColumn; i <= lastColumn; i++) {
model.setValueAt(table.getModel().getValueAt(this.row, i), 0, i - firstColumn);
}
}
/**
* Implemented to return the original value as
* given in the
*/
@Override
public Object getCellEditorValue() {
return editingComponent.getText();
}
}
public static class ButtonRenderer implements TableCellRenderer {
JButton button = new JButton();
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
button.setText(value != null ? value.toString() : "");
return button;
}
}
// example usage
// source model is not editable except for the button column
final DefaultTableModel model = new DefaultTableModel(0, 3) {
@Override
public boolean isCellEditable(int row, int column) {
return column == 0;
}
};
for (int i = 0; i < 20; i++) {
model.addRow(new Object[] {"Edit", i});
}
JTable table = new JTable(model);
table.getColumnModel().getColumn(0).setCellRenderer(new ButtonRenderer());
final ButtonDialogEditor cellEditor = new ButtonDialogEditor(1, model.getColumnCount() - 1);
// custom editor listener which writes back the edited values
// to the model on editingStopped.
CellEditorListener l = new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
for (int i = cellEditor.firstColumn; i <= cellEditor.lastColumn; i++) {
model.setValueAt(cellEditor.getValueAt(i), cellEditor.getModelRow(), i);
}
}
@Override
public void editingCanceled(ChangeEvent e) {
// nothing to do
}
};
cellEditor.addCellEditorListener(l);
table.getColumnModel().getColumn(0).setCellEditor(
cellEditor);
回答by mKorbel
XxxTableModel
stores String.class
for JButton
as Renderer
/ Editor
for JTable
XxxTableModel
存储String.class
用于JButton
作为Renderer
/Editor
对JTable
and for your code (is based on) too
并且对于您的代码(基于)也是
EDIT
编辑
DefaultTableModel
默认表模型
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableButton3 extends JFrame {
private static final long serialVersionUID = 1L;
private JTable table;
public TableButton3() {
String[] columnNames = {"Date", "String", "Decimal", "Remove"};
Object[][] data = {
{new Date(), "A", new Double(5.1), "Remove"}, {new Date(), "B", new Double(6.2), "Remove"},
{new Date(), "C", new Double(7.3), "Remove"}, {new Date(), "D", new Double(8.4), "Remove"},
{new Date(), "A", new Double(5.1), "Remove"}, {new Date(), "B", new Double(6.2), "Remove"},};
DefaultTableModel model = new DefaultTableModel(data, columnNames){
private static final long serialVersionUID = 1L;
@Override// Returning the Class of each column will allow different renderers to be used based on Class
public Class getColumnClass(int column) {
switch (column) {
case 0:
return Date.class;
case 2:
return Double.class;
default:
return String.class;
}
//return getValueAt(0, column).getClass();
}
};
table = new JTable(model) ;
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
ButtonColumn buttonColumn = new ButtonColumn(table, delete, 3);
buttonColumn.setMnemonic(KeyEvent.VK_D);
}
public static void main(String[] args) {
TableButton3 frame = new TableButton3();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
//
private Action delete = new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
JTable table = (JTable) e.getSource();
int modelRow = Integer.valueOf(e.getActionCommand());
((DefaultTableModel) table.getModel()).removeRow(modelRow);
table.clearSelection();
}
};
}
AbstractTableModel
抽象表模型
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableButton3 extends JFrame {
private static final long serialVersionUID = 1L;
private JTable table;
private MyTableModel myModel = new MyTableModel();
public TableButton3() {
String[] columnNames = {"Date", "String", "Decimal", "Remove"};
Object[][] data = {
{new Date(), "A", new Double(5.1), "Remove"}, {new Date(), "B", new Double(6.2), "Remove"},
{new Date(), "C", new Double(7.3), "Remove"}, {new Date(), "D", new Double(8.4), "Remove"},
{new Date(), "A", new Double(5.1), "Remove"}, {new Date(), "B", new Double(6.2), "Remove"},};
DefaultTableModel model = new DefaultTableModel(data, columnNames){
private static final long serialVersionUID = 1L;
@Override// Returning the Class of each column will allow different renderers to be used based on Class
public Class getColumnClass(int column) {
switch (column) {
case 0:
return Date.class;
case 2:
return Double.class;
default:
return String.class;
}
//return getValueAt(0, column).getClass();
}
};
table = new JTable(model);
table = new JTable(myModel);
addTableDatas();
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
ButtonColumn buttonColumn = new ButtonColumn(table, delete, 3);
buttonColumn.setMnemonic(KeyEvent.VK_D);
}
public static void main(String[] args) {
TableButton3 frame = new TableButton3();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private void addTableDatas() {
Vector<String> columnNameS = new Vector<String>();
columnNameS.add("Date");
columnNameS.add("String");
columnNameS.add("Decimal");
columnNameS.add("Remove");
myModel.setColumnNames(columnNameS);
Vector<Object> row1 = new Vector<Object>();
row1.add(new Date());
row1.add("A");
row1.add(new Double(5.1));
row1.add("Remove");
myModel.addRow(row1);
row1 = new Vector<Object>();
row1.add(new Date());
row1.add("B");
row1.add(new Double(6.2));
row1.add("Remove");
myModel.addRow(row1);
row1 = new Vector<Object>();
row1.add(new Date());
row1.add("B");
row1.add(new Double(8.4));
row1.add("Remove");
myModel.addRow(row1);
row1 = new Vector<Object>();
row1.add(new Date());
row1.add("B");
row1.add(new Double(5.1));
row1.add("Remove");
myModel.addRow(row1);
row1 = new Vector<Object>();
row1.add(new Date());
row1.add("B");
row1.add(new Double(6.2));
row1.add("Remove");
myModel.addRow(row1);
}
private class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private Vector<Vector<Object>> data;
private Vector<String> colNames;
private boolean[] _columnsVisible = {true, true, true, true};
public MyTableModel() {
this.colNames = new Vector<String>();
this.data = new Vector<Vector<Object>>();
}
public MyTableModel(Vector<String> colnames) {
this.colNames = colnames;
this.data = new Vector<Vector<Object>>();
}
public void resetTable() {
this.colNames.removeAllElements();
this.data.removeAllElements();
}
public void setColumnNames(Vector<String> colNames) {
this.colNames = colNames;
this.fireTableStructureChanged();
}
public void addRow(Vector<Object> data) {
this.data.add(data);
this.fireTableRowsInserted(data.size() - 1, data.size() - 1);
}
public void removeRowAt(int row) {
this.data.removeElementAt(row);
this.fireTableRowsDeleted(row - 1, data.size() - 1);
}
@Override
public int getColumnCount() {
return this.colNames.size();
}
@Override
public Class<?> getColumnClass(int colNum) {
switch (colNum) {
case 0:
return Date.class;
case 2:
return Double.class;
default:
return String.class;
}
}
@Override
public boolean isCellEditable(int row, int colNum) {
switch (colNum) {
default:
return true;
}
}
@Override
public String getColumnName(int colNum) {
return this.colNames.get(colNum);
}
@Override
public int getRowCount() {
return this.data.size();
}
@Override
public Object getValueAt(int row, int col) {
Vector<Object> value = this.data.get(row);
return value.get(col);
}
@Override
public void setValueAt(Object newVal, int row, int col) {
Vector<Object> aRow = data.elementAt(row);
aRow.remove(col);
aRow.insertElementAt(newVal, col);
fireTableCellUpdated(row, col);
}
public void setColumnVisible(int index, boolean visible) {
this._columnsVisible[index] = visible;
this.fireTableStructureChanged();
}
}
//
private Action delete = new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
JTable table = (JTable) e.getSource();
int modelRow = Integer.valueOf(e.getActionCommand());
((DefaultTableModel) table.getModel()).removeRow(modelRow);
table.clearSelection();
}
};
}
both returns the same GUI, with the same ...
两者都返回相同的 GUI,具有相同的 ...