如何获得 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
开始。更改 JList
的 ListModel
将强制 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);
}
}
}
我需要允许用户点击一个按钮进入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
开始。更改 JList
的 ListModel
将强制 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);
}
}
}