【问题标题】:How to have a list of selected items of JList?如何获得 JList 的选定项目列表?
【发布时间】:2015-03-26 18:38:32
【问题描述】:

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

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

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

    }
}

【问题讨论】:

    标签: java swing list listselectionlistener


    【解决方案1】:

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

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

    【讨论】:

    • 按照建议,我将 GroupLayout 添加到框架并调用了 revalidate 方法,但仍然有同样的问题
    【解决方案2】:

    我该如何解决这个问题

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

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

    我建议做的是稍微改变你的方法。

    首先使用一个或多个布局管理器,在开始时将“浏览”按钮、“分析”按钮和JList 添加到框架中。当用户选择一个目录时,构建一个新的ListModel,然后将它应用到你创建的JList。更改JListListModel 将强制JList 自动更新。

    详情请见Laying Out Components Within a Container

    我怎样才能知道从列表中选择了哪些项目。

    详情请见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);
            }
    
        }
    
    }
    

    【讨论】:

    • 我看到用什么建议我用 null 替换?
    • GridBagLayout 浮现在脑海中,但您可以结合使用 BorderLayoutFlowLayout,具体取决于您想要 UI 的复杂程度
    • 按照建议,我将 GroupLayout 添加到框架并调用了 revalidate 方法,但仍然有同样的问题
    • GroupLayout 是可用的最复杂的布局管理器,它比 GridBagLayout 更复杂,这说明了一些事情
    • 根据示例,BorderLayoutFlowLayout 的组合应该是一个好的开始
    猜你喜欢
    • 2014-05-09
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    • 1970-01-01
    • 2016-08-01
    • 2015-01-23
    相关资源
    最近更新 更多