Java 如何在其他窗口上生成独立的JFileChooser对话框?

Java 如何在其他窗口上生成独立的JFileChooser对话框?,java,swing,focus,jfilechooser,taskbar,Java,Swing,Focus,Jfilechooser,Taskbar,和问过类似问题的人一样,我也疯狂地试图“修复”我的JFileChooser对话框生成代码,直到我注意到它正在生成,但它出现在所有其他窗口下面,并且没有相关的任务栏图标(因此根本没有它存在的线索!) 我知道这些类似的问题: …但这些问题的答案似乎过于复杂,涉及到创建更多的GUI元素,我认为这是不必要的 我也知道关于不要混合控制台和Swing接口的建议,但我希望尽可能简单 我想知道如何生成位于其他窗口之上的JFileChooser(showOpenDialog)对话框,而不必创建其他GUI

和问过类似问题的人一样,我也疯狂地试图“修复”我的JFileChooser对话框生成代码,直到我注意到它正在生成,但它出现在所有其他窗口下面,并且没有相关的任务栏图标(因此根本没有它存在的线索!)

我知道这些类似的问题:

…但这些问题的答案似乎过于复杂,涉及到创建更多的GUI元素,我认为这是不必要的

我也知道关于不要混合控制台和Swing接口的建议,但我希望尽可能简单


我想知道如何生成位于其他窗口之上的JFileChooser(showOpenDialog)对话框,而不必创建其他GUI元素(JPanel等)。

注1:似乎在讨论解决方案,但很难遵循。
注2:如果我所要求的是不可能的,那么关于如何至少给对话框一个任务栏图标(同样不要求它有一个父项)的信息将非常好

我的代码现在创建了一个隐藏的对话框,如下所示:

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;

class Client {
    String currentDirectoryFolderPath = "H:\\myFolder";
    javax.swing.JFileChooser jFileChooser =
            new JFileChooser(currentDirectoryFolderPath);
    jFileChooser.setVisible(true); //defaults to invisible?!?
    javax.swing.filechooser.FileNameExtensionFilter fileExtensionFilter
            = new FileNameExtensionFilter(
              comma-separated values and text files",
              "csv", "txt");
    jFileChooser.setFileFilter(fileExtensionFilter);

    //int returnVal = jFileChooser.showOpenDialog(jFileChooser);
    //jFileChooser.showDialog(null, "testing 1--2--3");
    //jFileChooser.requestFocusInWindow();
    //jFileChooser.requestFocus();
    //jFileChooser.showOpenDialog(null);
    //jFileChooser.requestFocus();
    int returnVal = jFileChooser.showOpenDialog(null);

    if(returnVal == JFileChooser.APPROVE_OPTION) {
        System.out.println("You chose to open this file: " +
                           jFileChooser.getSelectedFile().getName());
    }

    System.out.println(JFileChooser.APPROVE_OPTION);
    System.out.println(jFileChooser);
}
注释代码是我尝试过的所有不起作用的东西,包括

  • 调用对话框前后不同类型的焦点请求,以及
  • 提供对话框对象本身作为它自己的父对象,而不是传递null(我认为这值得一试)

首先,您可以创建自己的对话框,并使用
setAlwaysOnTop
将窗口置于窗口z顺序的顶部。这是特定于操作系统的,因此可能无法在所有操作系统上运行

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FileChooser {

    public static void main(String[] args) {
        new FileChooser();
    }
    private int state = JFileChooser.ERROR_OPTION;

    public FileChooser() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFileChooser chooser = new JFileChooser();
                chooser.addPropertyChangeListener(new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        System.out.println(evt.getPropertyName());
                    }
                });
                chooser.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (JFileChooser.CANCEL_SELECTION.equals(e.getActionCommand())) {
                            state = JFileChooser.CANCEL_OPTION;
                            SwingUtilities.windowForComponent((JFileChooser) e.getSource()).dispose();
                        } else if (JFileChooser.APPROVE_SELECTION.equals(e.getActionCommand())) {
                            state = JFileChooser.APPROVE_OPTION;
                            SwingUtilities.windowForComponent((JFileChooser) e.getSource()).dispose();
                        }
                    }
                });
                JDialog dialog = new JDialog();
                dialog.setAlwaysOnTop(true);
                dialog.setTitle("Open it sucker");
                dialog.setModal(true);
                dialog.add(chooser);
                dialog.pack();
                dialog.setLocationRelativeTo(null);
                dialog.setVisible(true);
                switch (state) {

                    case JFileChooser.APPROVE_OPTION:
                        System.out.println("approved");
                        break;
                    case JFileChooser.CANCEL_OPTION:
                        System.out.println("cancled");
                        break;
                    default:
                        System.out.println("Broken");
                        break;

                }
            }
        });
    }
}

其次。如果你想得到一个任务图标,我认为你需要创建一个
JFrame
,而不是
JDialog
。这意味着框架在可见时不会阻塞,您需要依靠
ActionListener
向调用者提供反馈

另一个配置对话框的选项:将JFileChooser子类化并使用自定义设置覆盖其createDialog:

public static void main(String[] args) throws AWTException {
    Action action = new AbstractAction("open in tray") {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Please select the file");
            JFileChooser fc = new JFileChooser() {

                @Override
                protected JDialog createDialog(Component parent)
                        throws HeadlessException {
                    JDialog dialog = super.createDialog(parent);
                    // config here as needed - just to see a difference
                    dialog.setLocationByPlatform(true);
                    // might help - can't know because I can't reproduce the problem
                    dialog.setAlwaysOnTop(true);
                    return dialog;
                }

            };
            int retValue = fc.showOpenDialog(null);
            if(retValue == JFileChooser.APPROVE_OPTION){
                System.out.println(fc.getSelectedFile());
            }else {
                System.out.println("Next time select a file.");
            }
        }
    };
    TrayIcon trayIcon = new TrayIcon(XTestUtils.loadDefaultImage(), "open in tray");
    trayIcon.addActionListener(action);
    SystemTray.getSystemTray().add(trayIcon); 
}

我不能说这是否有帮助,因为我无法重现这个问题(Windows Vista,jdk7)-无论我怎么做,对话框都会出现在所有东西的顶部,可能高度依赖操作系统。

如果其他人偶然发现这个问题,我有一个可行的解决方案来创建一个带有相当优雅的任务栏图标的JFileChooser

JFileChooser chooser = new JFileChooser();
JDialog wrapper = new JDialog((Window)null);
wrapper.setVisible(true);
chooser.showDialog(wrapper);

显然,
wrapper
可以通过各种方式进行操作,例如设置位置、是否可调整大小等。使用
(Window)null
作为JDialog的父级会使对话框在任务栏中有一个图标,当您使用
showDialog
showOpenDialog
或任何您需要的东西时,JFileChooser会继承它,其父级是
包装器
对话框。

大多数情况下,我只想让事情保持简单。。。而且:如果您可以创建一个没有父对象(null)的文件选择器,那么您应该能够创建一个没有父对象的可用文件选择器。(否则,在没有父对象的情况下创建它有什么意义呢?)创建自己的对话框,将其始终设置在顶部,并向其添加一个
JFileChooser
it@MadProgrammer这听起来有点像,这很好(这正是我现在正在实现的),但它仍然需要一个额外的“片段”。我认为一个无关的对话框比一个无关的JFrame(如链接中所示)更整洁,因此,如果没有其他部分你绝对不能做到这一点,那么我会接受它作为一个答案(特别是如果这会产生一个任务栏项)。@MadProgrammer顺便说一句,你基本上是说一些对话框可以设置在顶部(它甚至不必是“始终在顶部”),但文件选择器对话框由于某些原因缺少这种功能。如果是真的,那就很奇怪了。我没有测试过它,但这听起来不错(如果比我希望的窗口正常运行要复杂得多的话)。setAlwaysOnTop在这里是必不可少的吗?难道没有办法让它像99%出现的其他新窗口一样工作,也就是说,一开始在顶部,但不总是在顶部吗?(我想将setAlwaysOnTop设置为true,然后立即再次设置为false可能会这样做,但这似乎是一个难题。)这也很好(尽管如此,如果仅仅为了阻止窗口以我不相信任何人会希望的方式运行,就需要这么多的复杂性,那真是太遗憾了)。我猜您的代码中需要setAlwaysOnTop,但我会很快试用它(包括不使用它)。@a.M.-正如我所说的:对我来说,它总是按照预期的方式运行(我努力让它显示在一个框架下;),所以在您的上下文/操作系统中可能有什么东西让它行为不端,这可能值得也可能不值得追踪