Search code examples
javaswingjlist

Double printing JList


I am not sure why everything is printing twice. For example, if you press "Male", then the program will print MaleMale. This is a part of a bigger program: I want gender (a String) to store the last selection. Is this code doing that?

DefaultListModel toAdd = new DefaultListModel();
toAdd.addElement("Male");
toAdd.addElement("Female");
toAdd.addElement("Others");

JList list = new JList();
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setBorder(new TitledBorder(null, "How do you identify yourself?", ` 
TitledBorder.CENTER, TitledBorder.TOP, null, null));
list.setBackground(SystemColor.info);
list.setBounds(57, 85, 244, 97);
list.setModel(toAdd);
frame.getContentPane().add(list);

list.addListSelectionListener(new ListSelectionListener() {

        public void valueChanged (ListSelectionEvent event) {
            int lastSelIx = list.getMaxSelectionIndex();
            gender = (String) list.getModel().getElementAt(lastSelIx);
            System.out.print(gender);
        }       
    );
}

Solution

  • There are two events generated each time when you click on an item in the list: The first one is created when you press the mouse button, and the second one when you release the button.

    (This is mainly relevant for more sophisticated patterns of range-selection, drag and drop, or the case where you press the button on one item and then drag the mouse to another item)

    The solution is to check whether the "selection value is still adjusting" in the ListSelectionListener. So you can just do something like

    if (event.getValueIsAdjusting()) return;
    

    in your event listener method.

    Here as a MCVE, together with a few other cleanups:

    import java.awt.SystemColor;
    
    import javax.swing.BorderFactory;
    import javax.swing.DefaultListModel;
    import javax.swing.JFrame;
    import javax.swing.JList;
    import javax.swing.ListSelectionModel;
    import javax.swing.SwingUtilities;
    import javax.swing.event.ListSelectionEvent;
    import javax.swing.event.ListSelectionListener;
    
    public class JListSelectionDoubleEvent
    {
        public static void main(String[] args)
        {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    
        private static void createAndShowGui()
        {
            DefaultListModel<String> listModel = new DefaultListModel<String>();
            listModel.addElement("Male");
            listModel.addElement("Female");
            listModel.addElement("Others");
    
            JList<String> list = new JList<String>(listModel);
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            list.setBorder(
                BorderFactory.createTitledBorder("How do you identify yourself?"));
            list.setBackground(SystemColor.info);
    
            list.addListSelectionListener(new ListSelectionListener()
            {
                @Override
                public void valueChanged(ListSelectionEvent event)
                {
                    if (event.getValueIsAdjusting())
                    {
                        //System.out.println("Adjusting. Ignore this");
                        return;
                    }
                    String gender = list.getSelectedValue();
                    System.out.print(gender);
                }
            });
    
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(list);
            frame.setSize(400, 400);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }