问题
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