Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows look and feel for JFileChooser

I'm trying to generate a JFileChooser that has the Windows look-and-feel. I couldn't find a method to change it, so I created a base class that extends JFileChooser that changes the UI with the following code:

public FileChooser(){
  this(null);
}
public FileChooser(String path){
   super(path);
   try {
      UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");

    } catch (Exception e) { System.err.println("Error: " + e.getMessage()); }

Then, in another class, I call

FileChooser chooser = new FileChooser(fileName);
int val = chooser.showOpenDialog(null);

but the dialog box that comes up has the Java look and feel. Any thoughts on how to change this? Is there a method of the JFileChooser class that I can use instead of this extended class?

Thank you!

like image 852
chama Avatar asked Feb 17 '10 16:02

chama


3 Answers

I know you can set the look and feel for the whole application, but what do you do if you like the cross platform look and feel but want the System Look and Feel for the JFileChoosers. Especially since the cross platform doesn't even have the right file icons (and looks completely cheesy.)

Here is what I did. It is definitely a hack...

public class JSystemFileChooser extends JFileChooser{
   public void updateUI(){
      LookAndFeel old = UIManager.getLookAndFeel();
      try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      } 
      catch (Throwable ex) {
         old = null;
      } 

      super.updateUI();

      if(old != null){
         FilePane filePane = findFilePane(this);
         filePane.setViewType(FilePane.VIEWTYPE_DETAILS);
         filePane.setViewType(FilePane.VIEWTYPE_LIST);

         Color background = UIManager.getColor("Label.background");
         setBackground(background);
         setOpaque(true);

         try {
            UIManager.setLookAndFeel(old);
         } 
         catch (UnsupportedLookAndFeelException ignored) {} // shouldn't get here
      }
   }



   private static FilePane findFilePane(Container parent){
      for(Component comp: parent.getComponents()){
         if(FilePane.class.isInstance(comp)){
            return (FilePane)comp;
         }
         if(comp instanceof Container){
            Container cont = (Container)comp;
            if(cont.getComponentCount() > 0){
               FilePane found = findFilePane(cont);
               if (found != null) {
                  return found;
               }
            }
         }
      }

      return null;
   }
}
like image 131
Riquochet Avatar answered Nov 02 '22 02:11

Riquochet


If you don't need to change the Look and Feel, could you try putting the UIManager.setLookAndFeel(..) line in the main method of your entry class?

That seems to work for me, though I am at a loss as to why it won't work the way you have set it upt.

like image 8
Luhar Avatar answered Nov 02 '22 03:11

Luhar


The problem is that the Look & Feel was already selected for you when you called super(path).

From the Java Tutorial for Look and Feel:

Note: If you are going to set the L&F, you should do it as the very first step in your application. Otherwise you run the risk of initializing the Java L&F regardless of what L&F you've requested. This can happen inadvertently when a static field references a Swing class, which causes the L&F to be loaded. If no L&F has yet been specified, the default L&F for the JRE is loaded. For Sun's JRE the default is the Java L&F, for Apple's JRE the Apple L&F, and so forth.

To remedy, you should do this (explanation located here) - replace your try/catch block with this code:

UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
this.pack();
like image 4
Timothy Avatar answered Nov 02 '22 03:11

Timothy