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

14,068

Solution 1

This example extends JFileChooser to handle the selections directly by overriding the approve and cancel methods.

class MyChooser extends JFileChooser {

    @Override
    public void approveSelection() {
        ...
    }

    @Override
    public void cancelSelection() {
        ...
    }
}

Solution 2

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 :(

Solution 3

Edit: According to @MadProgrammer this is not correct.

JFileChooser is a dialog which is designed to perform the Open and Save stuff. You can change the name of the button and probably remove the Cancel. But you can't make it open as a Panel.

However, it's a dialog and it'll require a fair bit of reworking to get it embedded in a page instead. The source is available though, so it's possible. You can reuse the javax.swing.filechooser classes.

Share:
14,068

Related videos on Youtube

Justin
Author by

Justin

Working hard to not be labeled an idiot and failing.

Updated on September 16, 2022

Comments

  • Justin
    Justin over 1 year

    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.

  • MadProgrammer
    MadProgrammer over 11 years
    Actually JFileChooser is a JComponent, which means you can add to another container. It simply has convenience methods that allows it to be wrapped in a JDialog
  • Philip Whitehouse
    Philip Whitehouse over 11 years
    Wow nice! I assume you just manually call all the setup functions then?
  • Justin
    Justin over 11 years
    You're answer seems to be the same as trashgod's which is not good news but at least I know for sure what I'm dealing with.
  • MadProgrammer
    MadProgrammer over 11 years
    I'd take a look at the FileSystemView, along with a JList or JTable, you'll get the basic functionality you're looking for. Shame that the JFileChooser just doesn't seem suited for extending in any meaningful manner :P
  • trashgod
    trashgod over 11 years
    See also this example that uses FileSystemView.
  • MadProgrammer
    MadProgrammer over 11 years
    @trashgod +1 I'd forgotten about that
  • trashgod
    trashgod over 11 years
    @Justin: The example cited here shows how easy it is to add() a file chooser to a layout.
  • Justin
    Justin over 11 years
    Excellent example. Thanks @trashgod !