Select a file path with Java Swing and do something with that selection

Justin picture Justin · Oct 2, 2012 · Viewed 13.3k times · Source

I have been reading up on JFileChooser in javax.swing.* I know the showOpenDialog() method will allow me to select a File and click 'choose' but I have a specific way I want it to work.

I want to use two JFileChooser's (probably side by side in a JPanel) to select a TO and FROM path and then click a button that will take the user input from both 'Chooser's and do something.

Perhaps if anyone has an example of just doing a single JFileChooser like this? Essentially just highlighting the file/directory in the chooser and clicking some OTHER button to take the input from the 'Chooser (also the JFileChoosers button's (cancel and choose) are hidden).

Most likely this 'other' button would just be a signal to the code to get the value from the JFileChooser object.

I'm hoping being new to Swing that there is another class I am missing that can do what I have described but it's just not coming up in Google searches I have been crafting.

Answer

MadProgrammer picture MadProgrammer · Oct 2, 2012

This is my first pass (I'm on my Mac at the mo, so I'm having some issues with walking the JDK source ;))

The problem is, getting rid of cancel and okay buttons...

enter image description here

public class TestFileChooser2 {

    public static void main(String[] args) {
        new TestFileChooser2();
    }

    public TestFileChooser2() {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new MainPane());
                frame.setSize(800, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            }
        });

    }

    protected class MainPane extends JPanel {

        private JFileChooser fileChooser;
        private JPanel filePane;

        private JTextField fileField;

        public MainPane() {

            setLayout(new BorderLayout());

            fileChooser = new JFileChooser();
            fileChooser.addPropertyChangeListener(new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (evt.getPropertyName().equals("SelectedFileChangedProperty")) {
                        File file = fileChooser.getSelectedFile();
                        if (file != null) {
                            setFile(file);
                        }
                    }
                }
            });

            add(fileChooser, BorderLayout.WEST);

            filePane = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            fileField = new JTextField(10);
            filePane.add(fileField, gbc);

            add(filePane);

        }

        protected void setFile(File file) {

            fileField.setText(file.getPath());

        }

    }
}

UPDATED

Apparently Windows doesn't like playing nice with the property change listener...

enter image description here

Make no mistake, this is a complete hack...

public class TestFileChooser2 {

    public static void main(String[] args) {
        new TestFileChooser2();
    }

    public TestFileChooser2() {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new MainPane());
                frame.setSize(800, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            }
        });

    }

    protected class MainPane extends JPanel {

        private JFileChooser fileChooser;
        private JPanel filePane;
        private JTextField fileField;

        public MainPane() {

            setLayout(new BorderLayout());

            fileChooser = new JFileChooser();
            fileChooser.setApproveButtonText("delete");
            removeButtons(fileChooser);

            JList list = findFirstChildren(fileChooser, JList.class);
            list.addListSelectionListener(new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent e) {
                    if (!e.getValueIsAdjusting()) {
                        File file = (File)((JList)e.getSource()).getSelectedValue();
                        if (file != null) {
                            setFile(file);
                        }
                    }
                }
            });

//            fileChooser.addPropertyChangeListener(new PropertyChangeListener() {
//                @Override
//                public void propertyChange(PropertyChangeEvent evt) {
//                    System.out.println(evt.getPropertyName());
//                    if (evt.getPropertyName().equals("SelectedFileChangedProperty")) {
//                        File file = fileChooser.getSelectedFile();
//                        if (file != null) {
//                            setFile(file);
//                        }
//                    }
//                }
//            });

            add(fileChooser, BorderLayout.WEST);

            filePane = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            fileField = new JTextField(10);
            filePane.add(fileField, gbc);

            add(filePane);

        }

        protected void setFile(File file) {

            fileField.setText(file.getPath());

        }

        protected void removeButtons(Container container) {
            for (Component child : container.getComponents()) {

                if (child instanceof JButton) {
                    JButton btn = (JButton) child;
                    if (btn.getText() != null && (btn.getText().equals(fileChooser.getApproveButtonText()) || btn.getText().equals("Cancel"))) {
                        container.remove(child);
                    }
                } else if (child instanceof Container) {
                    removeButtons((Container) child);
                }

            }
        }

        public <T extends Component> T findFirstChildren(JComponent component, Class<T> clazz) {

            T child = null;
            for (Component comp : component.getComponents()) {

                if (clazz.isInstance(comp)) {

                    child = (T) comp;
                    break;

                } else if (comp instanceof JComponent) {

                    child = findFirstChildren((JComponent) comp, clazz);
                    if (child != null) {
                        break;
                    }

                }

            }

            return child;

        }
    }
}

A better solution would be to utilise the FileSystemView directly and build you're own view, but that's more effort then I have time for right now :(