How to generate a stand-alone JFileChooser dialog box on top of other windows?

雨燕双飞 提交于 2019-12-06 10:25:26

问题


Like some other people who have asked similar questions, I was going nuts trying to 'fix' my JFileChooser dialog box generation code until I noticed that it is being generated, but it is appearing underneath all other windows and does not have an associated taskbar icon (so there was no clue at all that it existed!).

I am aware of these similar questions:

  • Bringing JFileChooser on top of all windows
  • JFileChooser from a command line program and popping up Underneath all windows

...but the answers to those questions seem overly complex, involving creating more GUI elements, which I can't believe would be required.

I am also aware of the advice here about not mixing console and Swing interfaces, but I want to keep things as simple as possible.


I would like to know how to generate a JFileChooser (showOpenDialog) dialog box that is above other windows without resorting to creating other GUI elements (JPanel etc.).

Note 1: This site seems to discuss a solution, but is hard to follow.
Note 2: If what I am asking for is impossible, then information about how to at least give the dialog box a taskbar icon (again without requiring it to have a parent) would be great.

My code, which right now creates a buried dialog box, is here:

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

The commented code is all of the things I have tried that have not worked, including

  • different types of request for focus before and after calling the dialog box, and
  • supplying the dialog box object itself as it's own parent instead of passing a null (I thought that was worth a shot.).

回答1:


Firstly, you could create your own dialog and use setAlwaysOnTop to bring the window to the top of the window z-order. This is OS specific so it might not work on all OSes...

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;

                }
            }
        });
    }
}

Secondly. If you want to get a task icon, I think you need to create a JFrame instead of a JDialog. This means that the frame won't block when made visible and you will need to rely on the ActionListener to provide feedback to the caller




回答2:


Another option to configure the dialog: which is to subclass JFileChooser and override its createDialog with custom settings:

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

Can't say if that might help because I can't reproduce the problem (Windows Vista, jdk7) - whatever I tried, the dialog appears on top of everything, probably highly OS dependent.




回答3:


In the event that anyone else stumbles across this, I have a working solution to create a JFileChooser with taskbar icon that's fairly elegant.

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

Obviously wrapper can be manipulated in various ways, e.g. setting location, whether it's resizable, etc. Using (Window)null as the parent of the JDialog causes the dialog to have an icon in the taskbar, which is inherited by the JFileChooser when you showDialog or showOpenDialog or whatever you need, with the parent being the wrapper dialog.



来源:https://stackoverflow.com/questions/17438630/how-to-generate-a-stand-alone-jfilechooser-dialog-box-on-top-of-other-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!