简体   繁体   中英

How to use Focus Events of Swing JSpinner in Java?

I am creating a Desktop Java Application (just for fun and expanding knowledge) using NetBeans. I have a Spinner (and a Button) in a Panel and I need to detect when the Spinner loses focus. I have tried several things but nothing will fire either focusGained or focusLost for the Spinner. How can I get this to work?

What I have tried:

ATTEMPT 1: I tried using "implements FocusListener" at the class level, then Overridding the focusGained and focusLost events as follows.

    @Override
    public void focusGained(FocusEvent e) {
        String name = e.getComponent().getClass().getName();
        System.out.println("Focus gained : " + name);
    }

    @Override
    public void focusLost(FocusEvent e) {
        String name = e.getComponent().getClass().getName();
        System.out.println("Focus lost : " + name);
    }

I added listeners as follows. I only had the commented out line at first. This worked perfectly for the button but the Spinner never fired either event when clicking on it, changing it, and then clicking off of it to the button. So then I tried commenting out that line and added the line below to try and use the underlying TextField. This again did not work.

        jButton1.addFocusListener(this);
        //jSpinner1.addFocusListener(this);
((JSpinner.DefaultEditor)jSpinner1.getEditor()).getTextField().addFocusListener(this);   

ATTEMPT 2: Next I removed the Class level FocusListener and tried building a new one inline as follows. Again I tried first building it directly on the Spinner and when that didn't work, I tried building it on the underlying TextField. Again neither event ever fired.

    //jSpinner1.addFocusListener(new FocusListener() {
    ((JSpinner.DefaultEditor)jSpinner1.getEditor()).getTextField().addFocusListener(new FocusListener() {
      @Override
      public void focusGained(FocusEvent e) {
        String name = e.getComponent().getClass().getName();          
        System.out.println("Focus gained : " + name);
      };
      @Override
      public void focusLost(FocusEvent e) {
        String name = e.getComponent().getClass().getName();          
        System.out.println("Focus lost : " + name);
      };
      });

ATTEMPT 3: Finally I tried building a separate focusAdapter as follows. Again I tried attaching it first directly to the Spinner and then to the underlying TextField and again neither event ever fired.

        FocusAdapter focusAdapter = new FocusAdapter()
        {
            public void focusGained(FocusEvent e)
            {
                String name = e.getComponent().getClass().getName();          
                System.out.println("Focus gained : " + name);
            }
            
            public void focusLost(FocusEvent e) {
                String name = e.getComponent().getClass().getName();          
                System.out.println("Focus lost : " + name);
            };            
        };        
        
        //jSpinner1.addFocusListener(focusAdapter);
        ((JSpinner.DefaultEditor)jSpinner1.getEditor()).getTextField().addFocusListener(focusAdapter);

I will add that I have tried using both AdoptOpenJDK jdk-11.0.11.9-hotspot and Oracle OpenJDK jdk-16.0.1 just to see if that might make a difference. Same results with both.

I should also add that I have made sure that both the "focusable" property and the "requestFocusEnabled" property of the Spinner are set to "true".

I am at a complete loss. All 3 methods should have worked and do with other non-Spinner components. Is focus just broken with Spinners or am I missing something?

Thanks to @MadProgrammer's tip I have the answer. I had the DateEditor and the setEditor lines below where I set the Listener. This was clearing the listener I had just set. I moved those two lines to before I set the Listener and now both sets of the following code work for me.

Using a FocusAdapter:

        JSpinner.DateEditor de = new JSpinner.DateEditor(jSpinner1, "h:mm:ss a");
        jSpinner1.setEditor(de);        
        
        FocusAdapter focusAdapter = new FocusAdapter()
        {
            public void focusGained(final FocusEvent e)
            {
                String name = e.getComponent().getClass().getName();          
                System.out.println("Focus gained : " + name);
            }
            
            public void focusLost(final FocusEvent e) {
                String name = e.getComponent().getClass().getName();          
                System.out.println("Focus lost : " + name);
            };            
        };        
        
        ((JSpinner.DefaultEditor)jSpinner1.getEditor()).getTextField().addFocusListener(focusAdapter);   

Using an inline Listener:

    ((JSpinner.DefaultEditor)jSpinner1.getEditor()).getTextField().addFocusListener(new FocusListener() {
      @Override
      public void focusGained(FocusEvent e) {
        String name = e.getComponent().getClass().getName();          
        System.out.println("Focus gained : " + name);
      };
      @Override
      public void focusLost(FocusEvent e) {
        String name = e.getComponent().getClass().getName();          
        System.out.println("Focus lost : " + name);
      };
      });

I suspect but haven't tried, that the first method I tried (in my original question above) would also work if I also moved those two lines to before I attached the Listener.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM