java swing jtable tablecelleditor documentfilter

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.