如何获得 JList 的选定项目列表?

How to have a list of selected items of JList?

我需要允许用户点击一个按钮进入select一个目录,然后我在列表中显示该目录的所有文件并允许他们select任意数量的文件。 select 读取文件后,我应该读取每个文件的第一行并将其放入新列表中。

到目前为止,我可以 select 目录并显示文件列表。但是,问题是应用程序不会显示文件列表,除非我调整 window 的大小。一旦我调整它的大小,列表就会刷新并显示文件。我该如何解决这个问题以及如何从列表中找出哪些项目 selected。

    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);

    }
}

不要在 Swing GUI 中使用空布局和绝对定位。相信这是制作像样的复杂 GUI 的最简单方法是新手的谬误,它最终会咬你一口,让你难以增强 GUI,这些 GUI 在一个平台和屏幕分辨率上看起来还不错,但看起来很僵硬对所有其他人来说都很糟糕。使用布局管理器。

如果您向容器添加新组件,请不要忘记在容器上调用revalidate()repaint()以允许Swing显示新添加的组件。

How can I solve the issue

有许多可能的解决方案,在您的情况下最简单的可能是在将 JList 添加到内容窗格后调用 revalidate,问题是,您选择了使用 null 布局 (frame.getContentPane().setLayout(null);),这使得调用 revalidate 毫无意义,因为这用于指示布局管理器他们需要更新其布局细节。

避免使用 null 布局,像素完美布局是现代 ui 设计中的一种错觉。影响组件个体大小的因素太多,none 是您可以控制的。 Swing 旨在与核心的布局管理器一起工作,丢弃这些将导致无穷无尽的问题和问题,您将花费越来越多的时间来尝试纠正

我建议您稍微改变一下您的方法。

首先使用一个或多个布局管理器,将 "browse" 按钮、"analyze" 按钮和 JList 添加到框架的开头。当用户选择一个目录时,build 一个新的 ListModel 然后将其应用到您创建的 JList 开始。更改 JListListModel 将强制 JList 自动更新。

有关详细信息,请参阅 Laying Out Components Within a Container

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

有关详细信息,请参阅 How to Use Lists

更新了示例

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);
        }

    }

}