将JFileChooser置于所有窗口之上

22

我的一个非常简单的文件选择对话框实现似乎存在问题,每次都需要将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();
有没有特定的属性/方法可以设置来解决这个问题?

你不应该做这些事情。我想知道这种情况的原因是否在你的代码的其他位置。例如,你是否混合使用了AWT组件和Swing组件? - Hovercraft Full Of Eels
实际上不是,那是整个程序中唯一使用 UI 的方法,其余部分仍然是纯控制台。关于导入,我只使用了 java.io.Filejava.util.Scannerjavax.swing.JFileChooser - Carlos
你能否创建并发布一个SSCCE(请点击链接),这是一个小的可编译、可运行的程序,展示你最好的解决方案尝试。然后我们可以检查你的代码,运行它,修改它,并最好地帮助你修复它。 - Hovercraft Full Of Eels
重新格式化的代码,请在不正确的情况下恢复。 - trashgod
如果从模态JFrame中调用FJFileChooser,会有影响吗? - Mike Fulton
3个回答

11

showOpenDialog() 的 API 是指 showDialog(),其中说:“如果父窗口是空的,则对话框不依赖任何可见窗口,它将位于外观和感觉相关的位置,例如屏幕中心。”

以下示例将文件选择器定位在我的 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 https://dev59.com/K17Va4cB1Zd3GeqPIUuv
 * @see https://dev59.com/22435IYBdhLWcg3w7kwK
 */
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);
                }
            }
        }
    }
}

我很感激你的努力和帮助,trashgod。然而,就像我之前所说的,有些(解决方案)对于我的当前水平来说似乎非常冗长和复杂。最初我以为这是我自己的一个简单错误,但现在我意识到它比我想象的要复杂一些,而且由于它不是必须的,只会在我的测试过程中对我有益,所以我想现在先放一放,专注于功能性。再次感谢,当时间不是限制因素时,我一定会尝试你的建议。 - Carlos
1
没问题,我已经相应地简化了示例。早期版本仍然可以访问: http://stackoverflow.com/posts/5129757/revisions - trashgod
更新示例以使用菜单/操作/弹出窗口。 - trashgod

5

我不确定你实际遇到的问题是什么(可能是你的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;
   }
};

这只是一个临时解决方案,通常情况下您不应该需要这样做。

没有用,这也没有解决问题,我开始觉得是NetBeans出了问题。谢谢你的帮助。 - Carlos
可以尝试使用以下代码替代:dialog.setAlwaysOnTop(true); ? - William Jarvis
这个解决方案对我很有用,当我将我的应用程序(一个JFrame)传递到超级构造函数中而不是传递“parent”时。谢谢! - Micah Stairs

3
fileSelect.showOpenDialog(this)

当然,this 必须是某种组件的一部分(您的主界面的JFrame或JPanel)。如果您希望对话框出现在前面,所有对话框都需要有父组件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接