将 JFileChooser 置于所有窗口之上

问题描述 投票:0回答:4

我似乎在非常简单地实现文件选择器对话框时遇到问题,每次都需要最小化 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();

我可以设置特定的属性/方法来解决问题吗?

java swing openfiledialog jfilechooser
4个回答
11
投票

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

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

这只是一个黑客解决方案,您通常不需要这样做。


3
投票
fileSelect.showOpenDialog(this)

当然,

this
必须是某种组件(主界面的 JFrame 或 JPanel)。 如果您希望所有对话框都位于前面,则它们都需要有一个父组件。


0
投票

您写道(在您的评论中):

其实不是,这是整个程序中唯一使用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);
    }
}
  • 方法 setAlwaysOnTop 确保
    JFrame
    将成为活动窗口。
  • 一旦显示
    JFrame
    JFileChooser
    就会立即显示。
  • 调用方法 exit 是必需的,因为显示
    JFrame
    会启动 事件调度线程 (EDT)。当主线程终止时,EDT 不会因此调用方法
    exit
    确保 JVM 终止。
© www.soinside.com 2019 - 2024. All rights reserved.