Halbort
Halbort

Reputation: 762

JList Item Selection

I was wondering if there is a way, by selecting an item with a JList, to let the program perform some code. This code should run every time a new item is selected.

Previously, I had added a listener. Here is a minimal example I made.

public class Driver {

    public static void main(String[] args) {
        JFrame frame = new ListFrame();
        frame.setVisible(true);
        frame.setSize(200,100);
    }

}

public class ListFrame extends JFrame {

    private JList<String> list; 
    private JScrollPane scrollPane;
    private String[] data = {"A","B","C"};
    private JButton addButton = new JButton("Add");

    public ListFrame() {
        setLayout(new BorderLayout());

        list = new JList<String>(data);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        scrollPane = new JScrollPane(list);

        add(scrollPane, BorderLayout.CENTER);
        add(addButton, BorderLayout.SOUTH);

        addButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                String newEntry = JOptionPane.showInputDialog("Add new entry.");
                String[] tempData = new String[data.length + 1];
                for(int i = 0; i < data.length; i++)
                    tempData[i] = data[i];
                tempData[data.length] = newEntry;
                data = tempData;
                list = new JList<String>(data);
                scrollPane.setViewportView(list);
            }

        });

        list.addListSelectionListener(
                new ListSelectionListener() {

                    @Override
                    public void valueChanged(ListSelectionEvent e) {
                        System.out.println("Hi");
                    }

        });
    }
}

However, when I click an item on the Jlist, nothing is printed.

Upvotes: 2

Views: 4031

Answers (1)

Catalina Island
Catalina Island

Reputation: 7126

Your example uses getSelectionModel() to get the the list's ListSelectionModel, and it adds your listener directly to the selection model. This bypasses the ListSelectionHandler, used internally by JList, which never gets a chance to fireSelectionValueChanged(). Instead, let JList add your listener:

list.addListSelectionListener(new ListSelectionListener() {...}

when I click an item on the JList, nothing is printed.

Your new example prints "Hi" when I click an item, but I see some problems:

  • Be sure to run on the event dispatch thread.

  • Check the ListSelectionEvent for details of what happened.

  • To add elements to the list, don't create a new JList; update the list's ListModel instead.

See How to Write a List Selection Listener for more; here's the example I tested.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class Driver {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            JFrame frame = new ListFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
        });
    }

    private static class ListFrame extends JFrame {

        private final String[] data = {"A", "B", "C"};
        private final DefaultListModel model = new DefaultListModel();
        private final JList<String> list = new JList<>(model);
        private final JButton addButton = new JButton("Add");

        public ListFrame() {
            for (String s : data) {
                model.addElement(s);
            }
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            add(new JScrollPane(list), BorderLayout.CENTER);
            add(addButton, BorderLayout.SOUTH);
            addButton.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    String newEntry = JOptionPane.showInputDialog("Add new entry.");
                    model.addElement(newEntry);
                }
            });
            list.addListSelectionListener(new ListSelectionListener() {

                @Override
                public void valueChanged(ListSelectionEvent e) {
                    if (!e.getValueIsAdjusting()) {
                        System.out.println(e.getFirstIndex() + " " + e.getLastIndex());
                    }
                }
            });
        }
    }
}

Upvotes: 3

Related Questions