I can't get this CellEditor
with a DocumentFilter
to work as i want. When i typed in the only editable column, insertString
from PlainDocument is never called and documentFilter neither. I think im not overriding something correctly but i can't figured out.
I made this Minimal, Complete, Tested and Readable example
//TODO include imports
public class Test {
private static final int EDITABLE_COLUMN = 1;
private final TableCellEditor cellEditor;
private final JTextField textfield;
private final PlainDocument document;
private JPanel panel;
private MyTableModel tableModel = new MyTableModel();
private JTable table = new JTable() {
{
getTableHeader().setReorderingAllowed(false);
setAutoCreateRowSorter(false);
setSurrendersFocusOnKeystroke(Boolean.TRUE);
}
@Override
public boolean isCellEditable(int row, int column) {
return convertColumnIndexToModel(column) == EDITABLE_COLUMN;
}
@Override
public TableCellEditor getCellEditor(int row, int column) {
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == EDITABLE_COLUMN) {
System.out.println(" ENTER HERE ");
return Test.this.cellEditor;
}
return super.getCellEditor(row, column);
}
@Override
public void changeSelection(
final int row, final int column, final boolean toggle, final boolean extend) {
super.changeSelection(row, column, toggle, extend);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if ((getCellEditor(row, column) != null && editCellAt(row, column))) {
JTextComponent comp = (JTextComponent) getEditorComponent();
comp.requestFocusInWindow();
comp.selectAll();
if (column == EDITABLE_COLUMN) {
System.out.println("Is the same editor instance ? " + (textfield == getEditorComponent()));
System.out.println("Is the same document instance ? " + (textfield.getDocument() == Test.this.document));
}
}
}
});
}
};
public Test() {
JScrollPane scroll = new JScrollPane(table);
table.setModel(tableModel);
panel = new JPanel(new BorderLayout());
//panel.add(busyComponent,BorderLayout.CENTER);
panel.add(scroll, BorderLayout.CENTER);
textfield = new JTextField();
textfield.setHorizontalAlignment(JTextField.RIGHT);
document = new PlainDocument() {
@Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
System.out.println("Working here");
super.insertString(offs, str, a);
}
};
document.setDocumentFilter(new MyDocumentFilter());
textfield.setDocument(document);
//this fixes to show all
textfield.setBorder(null);
cellEditor = new DefaultCellEditor(textfield);
//i also try this without success
//table.getColumnModel().getColumn(EDITABLE_COLUMN).setCellEditor(cellEditor);
tableModel.insertValue(new ItemRow("nonEditable", "Editable"));
}
private class ItemRow {
private String column1;
private String column2;
public ItemRow(String column1, String column2) {
this.column1 = column1;
this.column2 = column2;
}
public String getColumn1() {
return column1;
}
public void setColumn1(String column1) {
this.column1 = column1;
}
public String getColumn2() {
return column2;
}
public void setColumn2(String column2) {
this.column2 = column2;
}
}
private class MyTableModel extends AbstractTableModel {
public static final int COLUMN1_INDEX = 0;
public static final int COLUMN2_INDEX = 1;
private final List<ItemRow> data = new ArrayList<>();
private final String[] columnsNames = {
"Column1",
"Column2",};
private final Class<?>[] columnsTypes = {
String.class,
Integer.class
};
public MyTableModel() {
super();
}
@Override
public Object getValueAt(int inRow, int inCol) {
ItemRow row = data.get(inRow);
Object outReturn = null;
switch (inCol) {
case COLUMN1_INDEX:
outReturn = row.getColumn1();
break;
case COLUMN2_INDEX:
outReturn = row.getColumn2();
break;
default:
throw new RuntimeException("invalid column");
}
return outReturn;
}
@Override
public void setValueAt(Object inValue, int inRow, int inCol) {
System.out.println("Gets called ");
if (inRow < 0 || inCol < 0 || inRow >= data.size()) {
return;
}
ItemRow row = data.get(inRow);
switch (inCol) {
case COLUMN1_INDEX:
row.setColumn1(inValue.toString());
break;
case COLUMN2_INDEX:
row.setColumn2(inValue.toString());
break;
}
fireTableCellUpdated(inRow, inCol);
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return columnsTypes.length;
}
@Override
public String getColumnName(int inCol) {
return this.columnsNames[inCol];
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return this.columnsTypes[columnIndex];
}
/**
*
* @param row
*/
public void insertValue(ItemRow row) {
data.add(row);
fireTableRowsInserted(data.size() - 1, data.size() - 1);
}
}
private class MyDocumentFilter extends DocumentFilter {
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
JOptionPane.showMessageDialog(null, "Enter hereeeeeeeee");
super.insertString(fb, offset, string, attr);
}
}
private static void createAndShowGUI(final Container container, final String title) {
//Create and set up the window.
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(Boolean.TRUE);
frame.add(container);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
createAndShowGUI(new Test().panel, "Test");
}
});
}
}
You're incompletely overriding the class. Try this for a change:
The class has 3 methods that may be overridden, and you've overridden only one of them.