Reputation: 9103
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
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
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