java - CellEditor con DocumentFilter nunca se llama
swing jtable (1)
No puedo hacer que este CellEditor
con un DocumentFilter
funcione como yo quiero. Cuando insertString
la única columna editable, insertString
de PlainDocument nunca se llama y documentFilter tampoco. Creo que no estoy anulando algo correctamente, pero no puedo descifrarlo.
Hice este ejemplo mínimo, completo, probado y legible
//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");
}
});
}
}
Estás anulando por completo la clase. Prueba esto para un cambio:
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);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attrs) throws BadLocationException {
JOptionPane.showMessageDialog(null, "This is really what you should be overriding");
super.replace(fb, offset, length, text, attrs);
}
@Override
public void remove(FilterBypass fb, int offset, int length)
throws BadLocationException {
JOptionPane.showMessageDialog(null, "and don''t forget this!");
super.remove(fb, offset, length);
}
}
La clase tiene 3 métodos que pueden anularse, y ha anulado solo uno de ellos.