JList duplicating selection
Asked Answered
A

2

6

I'm trying my hand at using Swing and decided to focus on using JList in conjunction with an arraylist of Objects.

I wanted to create a program that displayed a blank JList that when a button is pressed would display the contents of the arraylist as well as allow single selection that would print out what ever was selected.

My current code does all of the above however when I click on a single entry on the JList it prints it out twice. I feel like this is a simple mistake that could be easily rectified but I've been reading through it and my brain has stopped cooperating.

Any help will be greatly appreciated. Thanks in advance :)

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


public class textarea {

    ArrayList <Pet> petList = new ArrayList <Pet> ();
    DefaultListModel model = new DefaultListModel();
    JList list = new JList();

    public static void main (String [] args){

        textarea gui = new textarea();
        gui.go();
    }

    public void go(){

        petList.add(new Pet("Lucy","Dog",5));
        petList.add(new Pet("Geoff","Cat",2));
        petList.add(new Pet("Hammond","Hamster",1));

        model = new DefaultListModel();
        for(Pet p:petList){
            model.addElement(p.toString());
        }

        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        JButton button = new JButton("view pets");
        button.addActionListener(new ButtonListener());


        JScrollPane scroller = new JScrollPane(list);
        scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        panel.add(scroller);

        list.setVisibleRowCount(4);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.addListSelectionListener(new ListSelectionListener(){
            public void valueChanged(ListSelectionEvent event){
                String selection = (String) list.getSelectedValue();
                System.out.println(selection);
            }
        });

        frame.getContentPane().add(BorderLayout.CENTER,panel);
        frame.getContentPane().add(BorderLayout.SOUTH,button);

        frame.setSize(350,300);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }//end go()

        class ButtonListener implements ActionListener{
        public void actionPerformed(ActionEvent event){
                list.setModel(model);
            }
        }//end ButtonListener

}
Artifice answered 10/4, 2012 at 22:53 Comment(2)
General comment: you should run GUI code in the EDT using SwingUtilities.invokeLater().Krasnodar
Thanks I will keep it in minds and change the code accordingly.Artifice
A
6

Short answer: add if (!event.getValueIsAdjusting()) around your print like so:

list.addListSelectionListener(new ListSelectionListener()
{
  public void valueChanged(ListSelectionEvent event)
  {
    if (!event.getValueIsAdjusting())
    {
      String selection = (String) list.getSelectedValue();
      System.out.println(selection);
    }
  }
});

Long answer: Two events are being fired. One fires when the mouse is clicked, and another fires when the mouse is released. We typically think of a click as a single action, but really it is composed over the mouse depression, any movements, and the mouse release. During these phases the contents of the selection can change. Run your code and try clicking on a row, dragging across to other rows, and releasing. You'll see events being fired every time the row changes. By only taking action when the value is no longer adjusting, you can fire on the 'final' state.

Source: ListSelectionEvent Javadocs and ListSelectionModel Javadocs

Anett answered 10/4, 2012 at 23:15 Comment(2)
Thanks Eric. Event handling makes more sense now after doing what you mentioned.Artifice
I'm glad to hear it was helpful. Welcome to Stack Overflow!Anett
L
3

Just tested your code. On item selection 2 events are sent. The only difference I can see is with the isAdjusting boolean. This is set to true the first time, false the second

Anyway, it seems that this is standard behavior

Lacework answered 10/4, 2012 at 23:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.