javaswinginputverifier

Java Swing JTextField setInputVerifier keep focus on TextField


I have a public class JdbDateTextField extends JTextField and in the constructor I add this.setInputVerifier(new ValidDateOrEmptyVerifier());.

I use class ValidDateOrEmptyVerifier extends InputVerifier to verify the format of the input.

If the input is in the wrong format and the user looses the focus of the JdbDateTextField, I return false in the ValidDateOrEmptyVerifier and the focus is gained again to the JdbDateTextField again.

This works if the user switches from the JdbDateTextField to another textField or presses a Button. If pressing a button and the format of the input in the is wrong then no action for the button is performed and the focus is still at the JdbDateTextField.

This is exactly what I want. The user can not leave the JdbDateTextField until he enters a valid string.

The problem is that the JdbDateTextField is in a JPanel which is in a JTabbedPane so I have a GUI with several tabs.

If I have the JdbDateTextField selected, enter a invalid input and then directly click on another tab it still switches the tab. So I was able to provide a wrong input.

My Question is:

Is there a way to perform an Input Verification which does not allow to execute any other event before it is true


Solution

  • The best solution I can think of is to assign the JTabbedPane a custom selection model which refuses to allow changing tabs unless the current InputVerifier succeeds:

    int index = tabbedPane.getSelectedIndex();
    
    tabbedPane.setModel(new DefaultSingleSelectionModel() {
        @Override
        public void setSelectedIndex(int index) {
            Component focusOwner =
                FocusManager.getCurrentManager().getFocusOwner();
    
            if (focusOwner instanceof JComponent) {
                JComponent c = (JComponent) focusOwner;
                InputVerifier verifier = c.getInputVerifier();
                if (verifier != null && !verifier.shouldYieldFocus(c)) {
                    return;
                }
            }
    
            super.setSelectedIndex(index);
        }
    });
    
    tabbedPane.setSelectedIndex(index);