JCombobox focusLost is not firing-why is that?
Asked Answered
D

2

9

I have a JCombobox in my code. I have added the FocusLost event. But it didn't fired anyway. I have tried lots of time but didn't find solution.

jcbItemType.addFocusListener(new java.awt.event.FocusAdapter() {
    public void focusLost(java.awt.event.FocusEvent evt) {
        jcbItemTypeFocusLost(evt);
    }
});

private void jcbItemTypeFocusLost(java.awt.event.FocusEvent evt)                                      
    {                                          
        // TODO add your handling code here:
        System.out.println("name=" + ((Component) evt.getSource()).getName());
        System.out.println("index=" + jcbItemType.getSelectedIndex());
    }

But nothing is printed in console. Please suggest me what I am doing wrong.

Digestive answered 24/4, 2012 at 6:58 Comment(0)
K
7
  • FocusListener isn't proper Listener for JComboBox, altogether with another Listener(s) can creating endless loop (especially Editable JComboBox),

  • FocusListener is asynchronous, sometimes is too hard to catch events is right orders especially in the cases that JComponents has added another Listener(s) too

example how to listening for Focus from derived JTextField / JFormattedTextField

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ComboBoxTwo extends JFrame implements ItemListener {

    private static final long serialVersionUID = 1L;
    private JComboBox mainComboBox;
    private JComboBox subComboBox;

    public ComboBoxTwo() {
        String[] items = {"Select Item", "Color", "Shape", "Fruit"};
        String[] subItems1 = {"Select Color", "Red", "Blue", "Green"};
        mainComboBox = new JComboBox(items);
        mainComboBox.addItemListener(this);
        mainComboBox.addFocusListener(fcsListener);
        add(mainComboBox, BorderLayout.WEST);
        subComboBox = new JComboBox(subItems1);
        subComboBox.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXX");
        subComboBox.addItemListener(this);
        add(subComboBox, BorderLayout.EAST);
    }

    @Override
    public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            if (e.getSource() == mainComboBox) {
                System.out.println("Source  : mainComboBox");
            } else if (e.getSource() == subComboBox) {
                System.out.println("Source  : subComboBox");
            }
        }
    }

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

            @Override
            public void run() {
                JFrame frame = new ComboBoxTwo();
                frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
//
    private FocusListener fcsListener = new FocusListener() {

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

        @Override
        public void focusLost(FocusEvent e) {
            dumpInfo(e);
        }

        private void dumpInfo(FocusEvent e) {
            System.out.println("Source  : " + name(e.getComponent()));
            System.out.println("Opposite : " + name(e.getOppositeComponent()));
            System.out.println("Temporary: " + e.isTemporary());
            final Component c = e.getComponent();//works for editable JComboBox too
            if (c instanceof JFormattedTextField) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        ((JFormattedTextField) c).selectAll();
                    }
                });
            } else if (c instanceof JTextField) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        ((JTextField) c).selectAll();
                    }
                });
            }
        }

        private String name(Component c) {
            return (c == null) ? null : c.getName();
        }
    };
}
Knott answered 24/4, 2012 at 7:12 Comment(3)
I have previously used itemStateChanged but it is problematic for my purpose and hence i want to use FocusLost event. Your example didn't work for me although you have comment as //works for editable JComboBox too. But it isn't working for me. Please advise. I am searching it for long time.Digestive
@Digestive in this form works as I expected, rest is noticed in my answer, use ItemListener for JComboBox, for example in the form as I posted here,Knott
@Digestive simple I don't understood for why reason you have to required FocusListener, for better help sooner edit your question with a SSCCEKnott
L
9

I have found a very simple way to solve this.

The JComboBox default editor has an internal class BasicComboBoxEditor$BorderlessTextField that is the component that gets and loses focus.

It can be accessed simply by

Component component = comboBox.getEditor().getEditorComponent();  
if (component instanceof JTextField) 
    JTextField borderlesstextfield = (JTextField) borderless;

Then add a focus listener like you would to any JTextField

borderlesstextfield.addFocusListener(new FocusListener() 
{
   public void focusGained(FocusEvent e) 
     {
     }
   public void focusLost(FocusEvent e) 
     {
     }
}});

Now you have a FocusListener that will respond as expected to gain and loss of focus for the ComboBox

Lange answered 24/6, 2013 at 21:6 Comment(2)
This worked perfectly and should be the accepted answer since it is far less convoluted!Konyn
I agree with @Xerus this answer is way more understandable and deserves to be the accepted answerBluish
K
7
  • FocusListener isn't proper Listener for JComboBox, altogether with another Listener(s) can creating endless loop (especially Editable JComboBox),

  • FocusListener is asynchronous, sometimes is too hard to catch events is right orders especially in the cases that JComponents has added another Listener(s) too

example how to listening for Focus from derived JTextField / JFormattedTextField

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ComboBoxTwo extends JFrame implements ItemListener {

    private static final long serialVersionUID = 1L;
    private JComboBox mainComboBox;
    private JComboBox subComboBox;

    public ComboBoxTwo() {
        String[] items = {"Select Item", "Color", "Shape", "Fruit"};
        String[] subItems1 = {"Select Color", "Red", "Blue", "Green"};
        mainComboBox = new JComboBox(items);
        mainComboBox.addItemListener(this);
        mainComboBox.addFocusListener(fcsListener);
        add(mainComboBox, BorderLayout.WEST);
        subComboBox = new JComboBox(subItems1);
        subComboBox.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXX");
        subComboBox.addItemListener(this);
        add(subComboBox, BorderLayout.EAST);
    }

    @Override
    public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            if (e.getSource() == mainComboBox) {
                System.out.println("Source  : mainComboBox");
            } else if (e.getSource() == subComboBox) {
                System.out.println("Source  : subComboBox");
            }
        }
    }

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

            @Override
            public void run() {
                JFrame frame = new ComboBoxTwo();
                frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
//
    private FocusListener fcsListener = new FocusListener() {

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

        @Override
        public void focusLost(FocusEvent e) {
            dumpInfo(e);
        }

        private void dumpInfo(FocusEvent e) {
            System.out.println("Source  : " + name(e.getComponent()));
            System.out.println("Opposite : " + name(e.getOppositeComponent()));
            System.out.println("Temporary: " + e.isTemporary());
            final Component c = e.getComponent();//works for editable JComboBox too
            if (c instanceof JFormattedTextField) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        ((JFormattedTextField) c).selectAll();
                    }
                });
            } else if (c instanceof JTextField) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        ((JTextField) c).selectAll();
                    }
                });
            }
        }

        private String name(Component c) {
            return (c == null) ? null : c.getName();
        }
    };
}
Knott answered 24/4, 2012 at 7:12 Comment(3)
I have previously used itemStateChanged but it is problematic for my purpose and hence i want to use FocusLost event. Your example didn't work for me although you have comment as //works for editable JComboBox too. But it isn't working for me. Please advise. I am searching it for long time.Digestive
@Digestive in this form works as I expected, rest is noticed in my answer, use ItemListener for JComboBox, for example in the form as I posted here,Knott
@Digestive simple I don't understood for why reason you have to required FocusListener, for better help sooner edit your question with a SSCCEKnott

© 2022 - 2024 — McMap. All rights reserved.