CellEditor with DocumentFilter never get called

2019-05-20 22:45发布

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");
                }

            });
        }

    }

1条回答
看我几分像从前
2楼-- · 2019-05-20 23:25

You're incompletely overriding the class. Try this for a change:

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);
  }
}

The class has 3 methods that may be overridden, and you've overridden only one of them.

查看更多
登录 后发表回答