Angelo Berlin
Angelo Berlin

Reputation: 346

setSelectedFile(File file) does not present selection in GUI of JFileChooser

The following code will print "pom.xml" to the console. But it will not mark the selected file in the GUI as if the user had done it with a mouse.

So how can I select AND highlight the selected file programmatically?

JFileChooser fc = new JFileChooser();

FileFilter filter = new FileNameExtensionFilter("POM",
        new String[] { "xml" });
fc.setAcceptAllFileFilterUsed(false);
fc.setFileFilter(filter);
fc.setCurrentDirectory(new File("./"));

fc.setSelectedFile(new File("pom.xml"));
System.out.println(fc.getSelectedFile());

fc.showOpenDialog(null);

This does the code:

enter image description here

But I want to see the selection:

enter image description here

Upvotes: 2

Views: 723

Answers (2)

Katy Saintin
Katy Saintin

Reputation: 1

This issue is old, but I succeed to resolve the problem in overriding JFileChooser class. My class will also update the JTextField that displays the selected file name. This works only on user click event but not by programming with setSelectedFile() or setCurrentDirectory().

Here the result of my class enter image description here

Here my code sample

public class MyFileChooser extends JFileChooser {
    public MyFileChooser() {
        super();
    }

    public MyFileChooser(String currentPath) {
        super(currentPath);
    }

    public MyFileChooser(File currentFile) {
        super(currentFile);
    }

    @Override
    protected JDialog createDialog(Component parent) throws HeadlessException {
        JDialog createDialog = super.createDialog(parent);
        Container contentPane = createDialog.getContentPane();
        
        //Fix bug described in stackoverflow.com
        //https://stackoverflow.com/questions/33945713/setselectedfilefile-file-does-not-present-selection-in-gui-of-jfilechooser
        fillSelectedDirectoryOrFile(contentPane);
        return createDialog;
    }

    /**
     * This method fill the TextField with the selectedFile or currentDirectory
     * @param container
     */
    private void fillSelectedDirectoryOrFile(Container container) {
        
        if (getCurrentDirectory() != null || getSelectedFile() != null) {
            JTextComponent textField = getfileNameTextField (container) ;
            if(textField != null) {
                String textToDisplay = getSelectedFile() != null ? getSelectedFile().getName() : getCurrentDirectory().getName();
                textField.setText(textToDisplay);
            }
            //Force selected file to current directory if no selected file
            if(getSelectedFile() == null) {
                setSelectedFile(getCurrentDirectory());
            }
        }

    }
    
    /**
     * This method return TextField component displays the selectedFile or currentDirectory
     * @param container
     */
    private JTextComponent getfileNameTextField (Container container) {
        JTextComponent fileNameTextField = null;
        if (container != null) {
            //First the JTextComponent that display the selected file name
            Component[] components = container.getComponents();
            for (Component comp : components) {
                if (comp instanceof JTextComponent) {
                    //Textfield is found
                    fileNameTextField = ((JTextComponent) comp);
                    break;
                }
                //Else continue recursively
                if (comp instanceof Container) {
                    fileNameTextField = getfileNameTextField((Container) comp);
                }
            }
        }
        
        return fileNameTextField;
    }
    
    
    public static void main(String[] args) {
        try {
            
            File file = File.createTempFile("MyFileTemp", "");
            System.out.println("Create file " + file.getAbsolutePath());
            JFileChooser myFileChooser = new MyFileChooser();
            myFileChooser.setSelectedFile(file);
            
            myFileChooser.showOpenDialog(new JFrame("JFileChooser Test"));
            
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Upvotes: 0

Freek de Bruijn
Freek de Bruijn

Reputation: 3622

This is an interesting issue, which might also depend on the Look & Feel (L&F) that is used. I have tested with the Metal L&F on Windows. The JFileChooser class does not seem to handle the visual selection of the initially selected file correctly.

In the JFileChooser.ensureFileIsVisible method, the current directory is changed (if necessary) and a call is made to the ensureFileIsVisible method. This method in my case ends up calling the sun.swing.FilePane.ensureFileIsVisible method, which appears to make sure that the selected file is scrolled into view in the JList or JTable that is used to display the files. However, when I look at what is happening with a debugger, the list of files seems to be uninitialized at that moment and the selected file is not found. This would otherwise be the perfect time to select it in the user interface.

If you really want to solve this, it would perhaps be best to modify a L&F or create a new one, but this sounds like a lot of work to me. The following code is a quick and dirty hack that I wrote while looking into the issue that also seems to fix the issue, but it is clearly not production ready and I would not want to use it for anything important - use at your own risk:

import java.awt.*;
import java.io.File;
import javax.swing.*;
import javax.swing.filechooser.*;

public class SelectedFileChooser {
    public static void main(String[] arguments) {
        SwingUtilities.invokeLater(() -> new SelectedFileChooser().createAndShowGui());
    }

    private void createAndShowGui() {
        JFrame frame = new JFrame("Stack Overflow");
        frame.setBounds(100, 100, 800, 600);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        JButton openButton = new JButton("Test open");
        panel.add(openButton);
        frame.getContentPane().add(panel);

        openButton.addActionListener(actionEvent -> testOpen());

        frame.setVisible(true);
    }

    private void testOpen() {
        String directory = "./.idea/";
        String fileName = "compiler.xml";

        JFileChooser fc = new JFileChooser();

        FileFilter filter = new FileNameExtensionFilter("POM", "xml");
        fc.setAcceptAllFileFilterUsed(false);
        fc.setFileFilter(filter);
        fc.setCurrentDirectory(new File(directory));

        fc.setSelectedFile(new File(directory + fileName));
        System.out.println(fc.getSelectedFile().getAbsolutePath());

        createAndStartMonitorThread(fc, fileName);

        fc.showOpenDialog(null);
    }

    private void createAndStartMonitorThread(JFileChooser fc, String fileName) {
        Thread monitorThread = new Thread(){
            private int counter;

            @Override
            public void run() {
                while (counter < 20) {
                    System.out.println("Monitoring (" + counter + ")...");
                    monitorComponents(fc.getComponents(), "", fileName);
                    System.out.println("------");
                    try {
                        sleep(60);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    counter++;
                }
            }
        };

        monitorThread.start();
    }

    private void monitorComponents(Component[] components, String prefix,
                                   String fileName) {
        for (Component component : components) {
            if (component instanceof Container) {
                Container container = (Container) component;
                if (container.getComponentCount() > 0) {
                    monitorComponents(container.getComponents(), prefix + "    ",
                                      fileName);
                }
            }

            if (component instanceof JList || component instanceof JTable) {
                System.out.println(prefix + "[" + component.getClass().getName()
                                   + "] " + component);

                if (component instanceof JList) {
                    selectInList((JList) component, fileName);
                } else {
                    selectInTable((JTable) component, fileName);
                }
            }
        }
    }

    private void selectInList(JList list, String fileName) {
        int rowIndexToSelect = -1;
        System.out.println("list size: " + list.getModel().getSize());
        for (int rowIndex = 0; rowIndex < list.getModel().getSize(); rowIndex++) {
            Object value = list.getModel().getElementAt(rowIndex);
            System.out.println("Value at [" + rowIndex + ", 0] == " + value);
            if (value.toString().endsWith(fileName)) {
                rowIndexToSelect = rowIndex;
            }
        }

        System.out.println("Before change - list selection: "
                           + list.getSelectionModel().getMinSelectionIndex() + ".."
                           + list.getSelectionModel().getMaxSelectionIndex());

        if (rowIndexToSelect != -1) {
            list.getSelectionModel().setSelectionInterval(rowIndexToSelect,
                                                          rowIndexToSelect);

            System.out.println("After change - list selection: "
                               + list.getSelectionModel().getMinSelectionIndex() + ".."
                               + list.getSelectionModel().getMaxSelectionIndex());
        }

        System.out.println();
    }

    private void selectInTable(JTable table, String fileName) {
        int rowIndexToSelect = -1;
        System.out.println("table row count: " + table.getModel().getRowCount());
        for (int rowIndex = 0; rowIndex < table.getModel().getRowCount(); rowIndex++) {
            Object value = table.getModel().getValueAt(rowIndex, 0);
            System.out.println("Value at [" + rowIndex + ", 0] == " + value);
            if (value.toString().endsWith(fileName)) {
                rowIndexToSelect = rowIndex;
            }
        }

        System.out.println("Before change - table selection: "
                           + table.getSelectionModel().getMinSelectionIndex() + ".."
                           + table.getSelectionModel().getMaxSelectionIndex());

        if (rowIndexToSelect != -1) {
            table.getSelectionModel().setSelectionInterval(rowIndexToSelect,
                                                           rowIndexToSelect);

            System.out.println("After change - table selection: "
                               + table.getSelectionModel().getMinSelectionIndex() + ".."
                               + table.getSelectionModel().getMaxSelectionIndex());
        }

        System.out.println();
    }
}

Upvotes: 3

Related Questions