Hot questions for Using JTextField in tablecelleditor

Top Java Programmings / JTextField / tablecelleditor

Question:

I have tried to keep my JTable's tight and secure, making only editable columns editable via isCellEditable(). However, my clients are insisting that they want to double click on a cell so they can copy its contents, even if it is read only. I could let the cell be editable and not do anything with any edits they could make in the setValueAt() (so it reverts back to original value when editor exits). But I don't want this application to feel so freeform. Is there an easy effective way to make the JTextField used as the cell editor to allow selecting of text in the editor, but not editable?

I tried this override on my JTable below, but I don't think I'm looking for the right "instanceof" object.

@Override
public TableCellEditor getDefaultEditor(Class<?> columnClass) {
    if (super.getDefaultEditor(columnClass) instanceof JTextField) {
        JTextField jTextField = new JTextField();
        jTextField.setEditable(false);
        return (TableCellEditor) jTextField;
    }
    if (columnClass == null) {
        return null;
    }
    else {
        Object editor = defaultEditorsByColumnClass.get(columnClass);
        if (editor != null) {
            return (TableCellEditor)editor;
        }
        else {
            return getDefaultEditor(columnClass.getSuperclass());
        }
    }
}

Answer:

However, my clients are insisting that they want to double click on a cell so they can copy its contents, even if it is read only.

Create a custom editor that uses a readonly text field:

JTextField tf = new JTextField();
tf.setEditable(false);
DefaultCellEditor editor = new DefaultCellEditor( tf );
table.setDefaultEditor(Object.class, editor);

Use the keyboard or mouse to select the text you want to copy. Then you would then use Ctrl+C to copy the selected text. Or you could even add a popup menu to the text field and add a Copy menu item.

Question:

I have here a code I found in the stackoverflow which allows the table to have a custom cell editor as JTextField.

I have been reading some of the articles about cell editor and I understand some the behavior of each abstract method.

class tableText extends AbstractCellEditor implements TableCellEditor {
JComponent component = new JTextField();

public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,int rowIndex, int vColIndex) {
    ((JTextField) component).setText((String) value);
    return component;
}

public Object getCellEditorValue() {
    return ((JTextField) component).getText();
}

}

This code allowed me to add a JTextField when I want to edit a cell in my table but I am looking to add some code to it but Im not exactly sure where to put them.

The behavior I wanted to add was this:

When the cell is clicked and the JTextField appears, if the user pressed a numerical key, it will replace the old value with a new one.

If the cell's value was left blank, the original value will be retained.

I know how to make these codes, but I'm not sure where to put them.

Anyone can guide me on this?


Answer:

  1. If the user pressed a numeric key, it will replace the old value with a new one.

    As shown here, you should use a DefaultCellEditor with a JTextField for your cell editor. Override the table's editCellAt() method and select the editor's text so that the old value will be replaced immediately as the user types.

    final Component editor = getEditorComponent();
    …
    ((JTextComponent) editor).selectAll();
    

    If necessary, add a DocumentListener to examine individual keystrokes or a DocumentFilter to enforce numeric entry.

  2. If the cell's value was left blank, the original value will be retained.

    Press the Escape key to cancel editing and restore the original value.

Question:

I have a JTable whose cell editor is a JTextField, I am invoking focuslost on the celleditor whose code is

public void focusLost(FocusEvent e)
{
 JTextField textField = new JTextField();
 textField = (JTextField) e.getSource();
 textField.setText(getCurrencyEquivalent(textField.getText()));//read P.S
 table.setValueAt(textField.getText(), table.getEditingRow(), 0);
}

I'm getting the following exception:

java.lang.ArrayIndexOutOfBoundsException: -1

When I debugged, it was clear that the focuslost is triggered on the cellEditor after the the focus is actually Lost from the JTable's cell. Which makes table.getEditingRow() always return -1, hence it is highly impossible to dynamically set the values at focuslost. Help me solve this by any other technique, if available.

P.S: getCurrencyEquivalent() is a method that returns a formatted version of a given String in a different String format.


Answer:

getCurrencyEquivalent() is a method that returns a formatted version of a given String in a different String format.

Don't use a FocusListener to try to change the format of the data when it is edited.

Instead, you should be using a custom renderer to format the data. Check out Table Format Renderers for an easy example of how you can do this.

Question:

Ok, I notice a problem with my editor in JTable. The scenario looks like this :

  • I edit a cell and enter a valid value, lets say I enter 42
  • I double click on an other cell (which can be empty or not)
  • The cell now contain 42, I can edit this value but as I double click on the cell 42 is in the cell.

I suspect my editor because when I use DefaultCellEditor there is no problem. Here is its declaration :

public class GlobalEditor extends DefaultCellEditor {
public GlobalEditor(JTable table, JTextField jtf) {
    super(jtf);
    /*
     * Setting font, background/foreground color, center alignement
     */
}

public boolean stopCellEditing() {
    String value = ((JTextField) getComponent()).getText();
    if (!value.equals("")) {
        if (value.length() > 10) {
            ((JComponent) getComponent()).setBorder(new LineBorder(Color.red));
            return false;
        }
    }
    return super.stopCellEditing();
}

@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    JTextField ec = (JTextField) editorComponent;
    if(value != null && value+"" != "---")
        ec.setText(""+value);
    if (isSelected) {
        ec.selectAll();
    }

    return editorComponent;
}

}

This line this.setDefaultEditor(Object.class, new GlobalEditor(this, new JTextField())); sets my editor in my JTable constructor.

What am I missing ?


Answer:

Ok this worked :

JTextField ec = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);

Instead of (also return ec instead of editorComponent) :

JTextField ec = (JTextField) editorComponent;

In the getTableCellEditorComponent method.

Any explanation is welcomed !