Randomize
Randomize

Reputation: 9103

Java Swing: JTextField doesn't lose focus as expected

I have a JTable which has 2 columns. One of these columns is represented by a JTextField and the other one by a radio button.

The model is populated in this way:

   model.addRow(new Object[]{radioButton, ""});

Associated with the JTextField there is a cell editor like this:

class MyCellEditor extends DefaultCellEditor {

  MyCellEditor(JTextField textField) {
    super(textField);
    textField.addFocusListener(new FocusListener() {

        public void focusLost(FocusEvent e) {
            // do something if focus is lost
        }

        @Override
        public void focusGained(FocusEvent e) {
        }
    });
}

When I click on the JTextField cell I get a "blinking" cursor as expected so I can input my text in. Anyway if I click anywhere else in the main window I would expect that "focusLost(...)" method has been called but that happens only if I "play" a bit around in the window (like clicking in and out the jtextfield a few times).

Why the component doesn't lose the focus just after the first click to another external component?

Upvotes: 2

Views: 3660

Answers (2)

Randomize
Randomize

Reputation: 9103

I fixed like this:

1) Giving the focus to the new JTextField:

 if (editCellAt(getRowCount()-1, 1)) getEditorComponent().requestFocus();

2) Table auto-detects lost focus:

 table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

3) in "MyCellEditor class --> @Override public boolean stopCellEditing()" just check if the component whether has the focus or not:

 getComponent().isFocusOwner()

Upvotes: 0

mKorbel
mKorbel

Reputation: 109815

you can override stopEditing() in the TableCellEditor

or write directly

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

more complicated (JFormattedTextField) example

import java.awt.Component;
import java.awt.EventQueue;
import java.text.DecimalFormat;
import java.text.ParseException;
import javax.swing.*;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;

public class EditorAsRendererTableTest {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JTable table = new JTable(3, 2);
                TableColumnModel colModel = table.getColumnModel();
                MyCellEditor both = new MyCellEditor();
                colModel.getColumn(0).setCellEditor(both);
                colModel.getColumn(0).setCellRenderer(both);
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.getContentPane().add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private static class MyCellEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {

        private static final long serialVersionUID = 1L;
        private JFormattedTextField renderer = new JFormattedTextField(DecimalFormat.getInstance());
        private JFormattedTextField editor;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            renderer.setValue(value);
            return renderer;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            editor = new JFormattedTextField(DecimalFormat.getInstance());
            editor.setValue(value);
            return editor;
        }

        @Override
        public boolean stopCellEditing() {
            try {
                editor.commitEdit();
            } catch (ParseException e) {
                return false;
            }
            return super.stopCellEditing();
        }

        @Override
        public Object getCellEditorValue() {
            return editor.getValue();
        }
    }

    private EditorAsRendererTableTest() {
    }
}

Upvotes: 4

Related Questions