你的第一个问题来了
int returnVal = this.dynamicChooser.showDialog(this.frame, "Open");
它调用底层JFileChooser的showDialog方法,所以它正在构建自己的窗口,忽略你的
更好的解决方案是按需创建JDialog 并使用它来容纳您的文件选择器和其他控件
有点像……
public class MyFileChooser {
private final boolean isFilesOnly;
private static final MyFileChooser INSTANCE_FILES = new MyFileChooser(true);
private static final MyFileChooser INSTANCE_DIRS = new MyFileChooser(false);
private final JFileChooser dynamicChooser;
private MyFileChooser(boolean filesOnly) {
this.isFilesOnly = filesOnly;
this.dynamicChooser = new JFileChooser();
dynamicChooser.setControlButtonsAreShown(false);
this.chooserSetup();
}
public MyFileChooser getInstance(boolean filesOnly) {
if (filesOnly) {
return MyFileChooser.INSTANCE_FILES;
} else {
return MyFileChooser.INSTANCE_DIRS;
}
}
public void frameSetup(Container parent) {
// jframe setup code
parent.add(this.dynamicChooser);
}
public void chooserSetup() {
if (this.isFilesOnly) {
this.dynamicChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
} else {
this.dynamicChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
this.dynamicChooser.setMultiSelectionEnabled(true);
this.dynamicChooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
}
public File[] showOpenDialog(Component parent, String title) {
JDialog dialog = new JDialog(parent == null ? null : SwingUtilities.getWindowAncestor(parent), title);
dialog.setModal(true);
frameSetup(dialog);
dialog.pack();
dialog.setLocationRelativeTo(parent);
dialog.setVisible(true);
return dynamicChooser.getSelectedFiles();
}
}
其目的是模仿JFileChooser 中的showDialog 的动作。在这个例子中,我隐藏了“普通”控制按钮,因为我假设你会提供你自己的,通过它你可以更改返回文件
现在,如果您仍想使用标准按钮控件,可以将ActionListener 附加到JFileChooser
dynamicChooser.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
//...
}
});
我在测试时,取消按钮返回CancelSelection,选择按钮返回ApproveSelection
现在,因为我的示例使用动态对话框,您可能需要创建一个动态的ActionListener 来控制对话框,因为您不想在不删除它们的情况下继续将ActionListeners 添加到FileChooser ,类似...
public File[] showOpenDialog(Component parent, String title) {
JDialog dialog = new JDialog(parent == null ? null : SwingUtilities.getWindowAncestor(parent), title);
dialog.setModal(true);
frameSetup(dialog);
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
//..
dialog.dispose();
}
};
dynamicChooser.addActionListener(listener);
dialog.pack();
dialog.setLocationRelativeTo(parent);
dialog.setVisible(true);
dynamicChooser.removeActionListener(listener);
return dynamicChooser.getSelectedFiles();
}
举个例子
观察
因为我知道如果我不这样做,有人会踢我以遏制……
Java 中的 Sington's 是棘手的事情,关于这个主题有无数的线程,但是,通常认为(现在)最好的方法是使用 enum,它可以解决所有旧的同步问题
因此,您可以考虑使用类似..的东西
public static enum MyFileChooser {
INSTANCE_FILES(true),
INSTANCE_DIRS(false);
private final boolean isFilesOnly;
private final JFileChooser dynamicChooser;
private MyFileChooser(boolean filesOnly) {
this.isFilesOnly = filesOnly;
this.dynamicChooser = new JFileChooser();
//dynamicChooser.setControlButtonsAreShown(false);
this.chooserSetup();
}
public void frameSetup(Container parent) {
// jframe setup code
parent.add(this.dynamicChooser);
}
public void chooserSetup() {
if (this.isFilesOnly) {
this.dynamicChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
} else {
this.dynamicChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
this.dynamicChooser.setMultiSelectionEnabled(true);
this.dynamicChooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
}
public File[] showOpenDialog(Component parent, String title) {
JDialog dialog = new JDialog(parent == null ? (JDialog)null : SwingUtilities.getWindowAncestor(parent), title);
dialog.setModal(true);
frameSetup(dialog);
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
//..
dialog.dispose();
}
};
dynamicChooser.addActionListener(listener);
dialog.pack();
dialog.setLocationRelativeTo(parent);
dialog.setVisible(true);
dynamicChooser.removeActionListener(listener);
return dynamicChooser.getSelectedFiles();
}
}
您可以简单地使用类似...的方式调用它
File[] files = MyFileChooser.INSTANCE_FILES.showOpenDialog(null, "Open");
“我已经提到我希望在选择器之间有 JLabels,”
我曾认为布置 cmets 只是阅读数千个可用示例中的任何一个,显然我错了
所以,对 frameSetup 方法的简单更新解决了这个问题...
public void frameSetup(Container parent) {
// jframe setup code
parent.setLayout(new BorderLayout());
parent.add(new JLabel("I'm on top"), BorderLayout.NORTH);
parent.add(this.dynamicChooser);
parent.add(new JLabel("I'm on bottom"), BorderLayout.SOUTH);
}
查看How to Use BorderLayout了解更多详情
为了确保它正常工作,我更新了 showOpenDialog 方法以使用
frameSetup(dialog.getContentPane());
这不仅仅是传递JDialog 的实例,而是确保我们正在影响正确的容器