Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JList duplicating selection

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

}
like image 867
skon Avatar asked Apr 10 '12 22:04

skon


2 Answers

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

like image 90
Eric Grunzke Avatar answered Sep 28 '22 09:09

Eric Grunzke


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

like image 22
ControlAltDel Avatar answered Sep 28 '22 07:09

ControlAltDel