1

Is it possible to get location of selected element in JList? I would like to get it to place JFrame just below clicked option.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Lucas Wa
  • 530
  • 1
  • 6
  • 15

2 Answers2

6

You'll want to use JList#getCellBounds

int selectedIndex = list.getSelectedIndex();
Rectangle bounds = list.getSelectedBounds(selectedIndex, selectedIndex);

This will give you the location of the selected item within context to the JList, you'll need to translate this to screen space...

Point p = bounds.getLocation();
SwingUtilities.convertPointToScreen(p, list);

You may also want to take a look at The Use of Multiple JFrames: Good or Bad Practice?

For example...

import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class List {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new List();
    }

    public List() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                final JFrame selected = new JFrame("Selected");
                selected.add(new JLabel("Here I am"));
                selected.pack();

                DefaultListModel model = new DefaultListModel();
                for (int index = 0; index < 1000; index++) {
                    model.addElement("#" + index);
                }
                final JList list = new JList(model);
                list.addListSelectionListener(new ListSelectionListener() {
                    @Override
                    public void valueChanged(ListSelectionEvent e) {
                        int index = list.getSelectedIndex();
                        Rectangle bounds = list.getCellBounds(index, index);
                        Point p = bounds.getLocation();
                        p.y += bounds.height;
                        SwingUtilities.convertPointToScreen(p, list);
                        p.x -= selected.getWidth();
                        selected.setLocation(p);
                        selected.setVisible(true);
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(list));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}
Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
3

You can use indexToLocation() method of JList, for example:

import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class TestFrame extends JFrame {

    public TestFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        init();
        pack();
        setVisible(true);
    }

    private void init() {
        final JPopupMenu menu = new JPopupMenu("test");
        menu.add(new JMenuItem("1"));
        final JList<String> list = new JList<String>(new String[]{"1","2","3"});
        list.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                int selectedIndex = list.getSelectedIndex();
                if(selectedIndex != -1){
                    Point indexToLocation = list.indexToLocation(selectedIndex);
                    Rectangle cellBounds = list.getCellBounds(selectedIndex, selectedIndex);
                    menu.show(list, indexToLocation.x, indexToLocation.y+cellBounds.height);
                }
            }
        });

        add(list);
    }

    public static void main(String... strings) {
        new TestFrame();
    }

}
alex2410
  • 10,904
  • 3
  • 25
  • 41
  • Interesting, but it doesn't provide the height of the selected item, meaning that your `JPopupMenu` will overlay the selected item...which as I understand it, isn't what the OP wanted...learnt something though ;) – MadProgrammer Jun 05 '14 at 11:33
  • @MadProgrammer , You are right, but I think OP can change `menu.show(list, indexToLocation.x, indexToLocation.y);` for showing in another location – alex2410 Jun 05 '14 at 11:41