This discussion is archived
5 Replies Latest reply: Mar 6, 2012 7:54 AM by Jörg RSS

How to keep the focus in a table cell as long as it is invalid?

Jörg Explorer
Currently Being Moderated
Hello,

if you run the following code and enter some alphabetic characters in the Integer column,
you can't get out of the cell as long as focus transfer is within the table. But if you click in the textfield,
the cell is left invalid. (If you click in the textfield immediately after the false edit, the cell even doesn't
show the red border)
I tried to attach a focusListener to the table, but that makes editing the table impossible.
I also could attach a focusListener to each and every other component of the form,
and checking the table there in focusGained - but that looks rather awkward.
How would you proceed?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class InvalidInput extends JFrame {

  public InvalidInput() {
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLayout(new FlowLayout());
    setSize(200, 200);
    setTitle("InvalidInput");
    final String HEADER[] = {"Integer", "String"};

    DefaultTableModel dtm= createTableModel(HEADER);
    dtm.addRow(new Object[] {new Integer(100), "Item 1"});
    dtm.addRow(new Object[] {new Integer(200), "Item 2"});
    final JTable table= new JTable(dtm);
/*
    table.addFocusListener(new FocusAdapter() {
      public void focusLost(FocusEvent e) { 
     System.out.println(table.isEditing());
     if (table.isEditing()) {
       boolean b= table.getCellEditor().stopCellEditing();
       System.out.println(b);
//       if (!b) table.requestFocusInWindow();
//       if (!b) table.changeSelection(table.getEditingRow(),
//                         table.getEditingColumn(), false, false);
       if (!b) {
         DefaultCellEditor editor= (DefaultCellEditor)table.getCellEditor();
         editor.getComponent().requestFocusInWindow();
       }
     }
      }
    });
*/
    JScrollPane scrollPane = new JScrollPane(table);
    scrollPane.setPreferredSize(new Dimension(195,55));
    add(scrollPane);
    JTextField tf= new JTextField(10);
    add(tf);
    setVisible(true);
  }


  public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
     new InvalidInput();
      }
    });
  }


  private DefaultTableModel createTableModel(Object[] columnNames) {
    DefaultTableModel tblModel= new DefaultTableModel(columnNames, 0) {
      public Class getColumnClass(int column) {
     return getValueAt(0, column)==null ? Object.class :
                               getValueAt(0, column).getClass();
      }
    };
    return tblModel;
  }

}
Edited by: Jörg on 04.03.2012 14:52

A big improvement is to apply
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
for this at least reverts the erroneous input to the last valid value.
Still I would prefer either to inform the user of this reversion or to red-border the erroneous cell;
for sometimes the [OK] button is at the bottom of a long form and putting one's eyes there for
clicking, one doesn't necessarily notice the reversion which happens at the top.
  • 1. Re: How to keep the focus in a table cell as long as it is invalid?
    Kleopatra Journeyer
    Currently Being Moderated
    Basically, you have to implement the cellEditor such that it returns false in stopCellEditing if the value isn't valid. SwingX has a NumberEditorEx which internally uses a JFormattedTextField, you might want to have a look for inspiration :-)

    In combination with terminateEditOnFocusLost, that gives a rather good user experience. Unfortunately still not the complete story, though: table misbehaves in not always going the recommended path when terminating an edit (f.i. internally simply removes the editor on column resizing) - so watch out for those and decide with which you may live and which need further work (it's a never-ending story :-(

    Cheers
    Jeanette
  • 2. Re: How to keep the focus in a table cell as long as it is invalid?
    800268 Expert
    Currently Being Moderated
    Jörg wrote:
    if you run the following code and enter some alphabetic characters in the Integer column,
    How would you proceed?
    If it is for number input, use a DocumentFilter to prevent the user from entering alphabetic characters at all (in addition, you still need to normal validation probably).
  • 3. Re: How to keep the focus in a table cell as long as it is invalid?
    Jörg Explorer
    Currently Being Moderated
    Thanks to both of you!

    @Jeanette
    In my real application I use a JFormattedTextField as editor. Checking my overridden stopCellEditing() method I become aware that the contents of JFormattedTextField (getText() or super.getCellEditorValue()) arrives there already reverted. Thus it's no wonder that I cannot return false.
    simply removes the editor on column resizing
    Yikes! - Fortunately the table in question is not resizable.
    SwingX has a NumberEditorEx
    How would you proceed if you didn't know that class and were looking for it? I still don't manage to navigate successfully on java.net.

    @Walter
    Never thought of this. Seeing that someone is checking for me (red border), I'd rather lazily let him continue doing the job. But a DocumentListener looks like being a way out.
  • 4. Re: How to keep the focus in a table cell as long as it is invalid?
    Kleopatra Journeyer
    Currently Being Moderated
    Jörg wrote:
    SwingX has a NumberEditorEx
    How would you proceed if you didn't know that class and were looking for it? I still don't manage to navigate successfully on java.net.
    would have expected you to have the sources in your IDE :-)

    Hmm ... would have expected the svn browser at java.net to be searchable, but it isn't - so here's the link:

    http://java.net/projects/swingx/sources/svn/content/trunk/swingx-core/src/main/java/org/jdesktop/swingx/table/NumberEditorExt.java?rev=4171

    Cheers
    Jeanette

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points