简体   繁体   中英

How to have a list of selected items of JList?

I need to allow users to click on a button to select a directory, then I show all files of the directory in a list and allow them to select any number of files. After selecting the files, I should read the first line of each file and put that in a new list for them.

So far I can select the directory and show a list of files. However, the problem is that the application wont show the list of files unless I resize the window. As soon as I resize it the list get refreshed and show the files. How can I solve the issue and how can I find out which items are selected from the list.

    private JFrame frame;
    final JFileChooser fc = new JFileChooser();
    private JScrollPane scrollPane;
    File directory;
    JList<File>  list;


    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Main window = new Main();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Main() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 785, 486);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        JButton btnChooseDirectory = new JButton("Choose Directory");
        btnChooseDirectory.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                int returnVal = fc.showOpenDialog(fc);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    directory = fc.getSelectedFile();
                    File[] filesInDir = directory.getAbsoluteFile().listFiles();
                    addFilesToList(filesInDir);
                }
            }
        });
        btnChooseDirectory.setBounds(59, 27, 161, 29);
        frame.getContentPane().add(btnChooseDirectory);



        JLabel lblFilesMsg = new JLabel("List of files in the directory.");
        lblFilesMsg.setBounds(20, 59, 337, 16);
        frame.getContentPane().add(lblFilesMsg);

        JButton btnParseXmls = new JButton("Analyze");
        btnParseXmls.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                for (File name : list.getSelectedValuesList()) {
                    System.err.println(name.getAbsolutePath());
                }
            }
        });
        btnParseXmls.setBounds(333, 215, 117, 29);
        frame.getContentPane().add(btnParseXmls);


    }

    private void addFilesToList(File[] filesInDir){

        list = new JList<File>(filesInDir);

        list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        list.setLayoutOrientation(JList.VERTICAL);

        scrollPane = new JScrollPane(list);
        scrollPane.setBounds(20, 81, 318, 360);
        frame.getContentPane().add(scrollPane);

    }
}

Don't use null layouts and absolute positioning with Swing GUI's. It's a newbie fallacy to believe that this is the easiest way to make decent complex GUI's, and it will bite you in the end, leaving you with difficult to enhance GUI's that are rigid, that look OK on one platform and screen resolution but that look terrible on all others. Use the layout managers.

If you add a new component to a container, don't forget to call revalidate() and repaint() on the container to allow Swing to display the newly added components.

How can I solve the issue

There are a number of possible solutions, the simplest in your case might be to call revalidate after you have added the JList to the content pane, the problem is, you've elected to use a null layout ( frame.getContentPane().setLayout(null); ) which makes calling revalidate pointless, as this is used to instruct the layout managers that they need to update their layout details.

Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

What I would suggest doing is changing your approach slightly.

Start by using one or more layout managers, add the "browse" button, "analyze" button and JList to the frame at the start. When the user selects a directory, build a new ListModel and then apply this to the JList you created to start with. Changing the ListModel of the JList will force the JList to update automatically.

See Laying Out Components Within a Container for more details

and how can I find out which items are selected from the list.

See How to Use Lists for more details

Updated with example

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

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

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

    public class TestPane extends JPanel {

        private JList listOfFiles;

        public TestPane() {
            setLayout(new BorderLayout());
            listOfFiles = new JList();
            add(new JScrollPane(listOfFiles));

            JPanel top = new JPanel();
            top.add(new JLabel("Pick a directory"));
            JButton pick = new JButton("Pick");
            pick.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JFileChooser fc = new JFileChooser();
                    fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                    int returnVal = fc.showOpenDialog(fc);
                    if (returnVal == JFileChooser.APPROVE_OPTION) {
                        File directory = fc.getSelectedFile();
                        File[] filesInDir = directory.getAbsoluteFile().listFiles();
                        addFilesToList(filesInDir);
                    }
                }

                protected void addFilesToList(File[] filesInDir) {
                    DefaultListModel<File> model = new DefaultListModel<>();
                    for (File file : filesInDir) {
                        model.addElement(file);
                    }
                    listOfFiles.setModel(model);
                }
            });
            top.add(pick);

            add(top, BorderLayout.NORTH);

            JPanel bottom = new JPanel();
            JButton analyze = new JButton("Analyze");
            bottom.add(analyze);

            add(bottom, BorderLayout.SOUTH);
        }

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM