我似乎在非常简单地实现文件选择器对话框时遇到问题,每次都需要最小化 Netbeans 才能实现它,而且现在测试变得非常令人沮丧。
我在网上看到了一些解决方案,包括SO,但似乎没有一个能够解决问题,而其他一些解决方案对于我目前的水平来说似乎非常冗长和复杂。
private void fileSearch() {
JFileChooser fileSelect = new JFileChooser();
int returnVal = fileSelect.showOpenDialog(null);
String pathToFile;
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fileSelect.getSelectedFile();
pathToFile = file.getAbsolutePath();
try {
P.binaryFileToHexString(pathToFile);
} catch (Exception e) {
System.out.print("Oops! there was an error there..." + e);
}
System.out.println("\nYou chose to open this file: " + file.getName());
}
}
我的一些尝试包括使用;
.requestFocus();
.requestFocusInWindow();
.setVisible();
我可以设置特定的属性/方法来解决问题吗?
showOpenDialog()
的API指的是showDialog()
,它说,“如果父级是null
,那么对话框依赖于不可见的窗口,并且它被放置在依赖于外观和感觉的窗口中位置,例如屏幕中心。”
下面的示例将选择器放置在我的 L&F 屏幕中央。您可能会看到它与您的相比如何。
package gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
/**
* @see http://stackoverflow.com/questions/8507521
* @see http://stackoverflow.com/questions/5129294
*/
public class ImageApp extends JPanel {
private static final int MASK =
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
private JFileChooser chooser = new JFileChooser();
private Action openAction = new ImageOpenAction("Open");
private Action clearAction = new ClearAction("Clear");
private JPopupMenu popup = new JPopupMenu();
private BufferedImage image;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ImageApp().create();
}
});
}
public void create() {
JFrame f = new JFrame();
f.setTitle("Title");
f.add(new JScrollPane(this), BorderLayout.CENTER);
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
menu.setMnemonic('F');
menu.add(new JMenuItem(openAction));
menu.add(new JMenuItem(clearAction));
menuBar.add(menu);
f.setJMenuBar(menuBar);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setSize(new Dimension(640, 480));
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public ImageApp() {
this.setComponentPopupMenu(popup);
popup.add("Popup Menu");
popup.add(new JMenuItem(openAction));
popup.add(new JMenuItem(clearAction));
}
@Override
public Dimension getPreferredSize() {
if (image == null) {
return new Dimension();
} else {
return new Dimension(image.getWidth(), image.getHeight());
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
private class ClearAction extends AbstractAction {
public ClearAction(String name) {
super(name);
this.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_C);
this.putValue(Action.ACCELERATOR_KEY,
KeyStroke.getKeyStroke(KeyEvent.VK_C, MASK));
}
@Override
public void actionPerformed(ActionEvent e) {
image = null;
revalidate();
repaint();
}
}
private class ImageOpenAction extends AbstractAction {
public ImageOpenAction(String name) {
super(name);
this.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_O);
this.putValue(Action.ACCELERATOR_KEY,
KeyStroke.getKeyStroke(KeyEvent.VK_O, MASK));
}
@Override
public void actionPerformed(ActionEvent e) {
int returnVal = chooser.showOpenDialog(chooser);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File f = chooser.getSelectedFile();
try {
image = ImageIO.read(f);
revalidate();
repaint();
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}
}
}
}
我不确定你的问题到底是什么(可能是你的 Netbeans....谁知道),但是你尝试过重写
createDialog
方法吗?
示例:
JFileChooser fc = new JFileChooser() {
@Override
protected JDialog createDialog(Component parent) throws HeadlessException {
// intercept the dialog created by JFileChooser
JDialog dialog = super.createDialog(parent);
dialog.setModal(true); // set modality (or setModalityType)
return dialog;
}
};
这只是一个黑客解决方案,您通常不需要这样做。
fileSelect.showOpenDialog(this)
当然,
this
必须是某种组件(主界面的 JFrame 或 JPanel)。
如果您希望所有对话框都位于前面,则它们都需要有一个父组件。
您写道(在您的评论中):
其实不是,这是整个程序中唯一使用UI的方法,其余的仍然是纯控制台。
换句话说,您想要将 GUI 组件添加到 控制台应用程序,而您的问题是 JFileChooser 不会成为活动窗口,即具有 键盘焦点的窗口。
如其他答案中所述,问题是您将
JFileChooser
[打开]对话框的父级设置为空。
下面的代码创建了一个最小的
JFrame
,用作 JFileChooser
对话框父级,也用作 顶级容器。在下面的代码中,通过控制台询问用户是否想要选择一个文件。如果答案是 Y,则会显示 JFileChooser
对话框。该对话框关闭后,系统会再次询问用户是否要选择文件。因此,一个带有 GUI 组件的控制台应用程序,据我所知,这就是您想要实现的目标。
(代码后的注释。)
import java.io.File;
import java.util.Scanner;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
public class SlctFile {
private static void fileSearch() {
JFrame frame = new JFrame();
frame.setAlwaysOnTop(true);
frame.setVisible(true);
JFileChooser fileSelect = new JFileChooser();
int returnVal = fileSelect.showOpenDialog(frame);
String pathToFile;
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fileSelect.getSelectedFile();
pathToFile = file.getAbsolutePath();
try {
P.binaryFileToHexString(pathToFile);
}
catch (Exception e) {
System.out.print("Oops! there was an error there..." + e);
}
System.out.println("\nYou chose to open this file: " + file.getName());
}
frame.dispose();
}
public static void main(String[] args) {
String answer;
Scanner stdin = new Scanner(System.in);
do {
System.out.print("Select file? ");
answer = stdin.nextLine();
if ("Y".equalsIgnoreCase(answer)) {
fileSearch();
}
} while ("Y".equalsIgnoreCase(answer));
System.exit(0);
}
}
JFrame
将成为活动窗口。JFrame
,JFileChooser
就会立即显示。JFrame
会启动 事件调度线程 (EDT)。当主线程终止时,EDT 不会因此调用方法 exit
确保 JVM 终止。