2

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:

...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.).
Community
  • 1
  • 1
A.M.
  • 627
  • 2
  • 8
  • 18
  • Mostly I just want to keep things simple. ...but also: If you can *create* a file chooser with no parent (null), then you should be able to create a *usable* file chooser with no parent. (Otherwise, what is the point of being able to create it with no parent?) – A.M. Jul 03 '13 at 02:33
  • 1
    Create your own dialog, set it always on top and add a `JFileChooser` to it – MadProgrammer Jul 03 '13 at 02:45
  • @MadProgrammer That sounds a bit like http://stackoverflow.com/questions/7494478/jfilechooser-from-a-command-line-program-and-popping-up-underneath-all-windows/7536734#7536734 , which is fine (that is actually exactly what I am implementing for now), but it still requires an extra 'piece'. I suppose an extraneous dialog is tidier than an extraneous JFrame (as in that link), though, so if you absolutely can't do this without some other piece, then I would accept it as an answer (especially if that would yield a taskbar item). – A.M. Jul 03 '13 at 03:06
  • @MadProgrammer By the way, you are basically saying that some dialogs *can* be set to on top (it doesn't even have to be 'always on top'), but the file chooser dialog lacks that ability for some reason. That is strange if true. – A.M. Jul 03 '13 at 03:08
  • [JDialog#setAlwaysOnTop](http://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#setAlwaysOnTop%28boolean%29). I've not tested it though – MadProgrammer Jul 03 '13 at 03:19

3 Answers3

3

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

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • This sounds good (if much more complex than I was hoping just to get a window to behave normally). Is setAlwaysOnTop essential here? Isn't there a way to get it to behave like 99% of other new windows that come up, i.e. on top at first but not stuck always on top? (I suppose setting setAlwaysOnTop to true and then immediately to false again might do it, but that seems like a kluge.) – A.M. Jul 04 '13 at 12:28
3

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.

kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • This is also good (though again, it's a shame if this much complexity is needed just to stop the window from *behaving in a way I can't believe anyone would ever want it to*). I am guessing setAlwaysOnTop is required in your code, but I will try it out (including without out it) soon. – A.M. Jul 04 '13 at 12:34
  • @A.M. - as I said: for me it is behaving as expected always (and I tried hard to make it show up below a frame ;), so there might be something in your context/OS letting it misbehave, which may or may not be worth tracking down – kleopatra Jul 04 '13 at 12:43
1

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.