javaswingjfilechooserjpopupmenu

Customizing JPopupMenu in JFileChooser: Accessing Internal Components


enter image description here

How can I access the JPopupMenu that is invoked from a JFileChooser and customize that (background, foreground, borders)? The issue is that the popup is created inside sun.swing.FilePane, which I cannot access because the sun.* packages are not accessible by default. Developing a new FileChooser is not feasible as a lot of work has already been done. Do you have any ideas?

I tried iterating through nested components, but since I couldn't import FilePane, it didn't yield any results.


Solution

  • I tried iterating through nested components, but since I couldn't import FilePane, it didn't yield any results.

    sun.swing.FilePane extends JPanel, you can search this JPanel instead and get the JPopupMenu.

    import java.awt.*;
    import java.util.Objects;
    import java.util.stream.Stream;
    import javax.swing.*;
    
    public class FileChooserPopupMenuTest {
      public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
          JFileChooser chooser = new JFileChooser();
          descendants(chooser)
              .filter(JPanel.class::isInstance)
              .map(c -> ((JPanel) c).getComponentPopupMenu())
              .filter(Objects::nonNull)
              .findFirst()
              .ifPresent(popup -> {
                popup.addSeparator();
                popup.add(new JCheckBoxMenuItem("JCheckBoxMenuItem"));
              });
          chooser.showOpenDialog(null);
        });
      }
    
      public static Stream<Component> descendants(Container parent) {
        return Stream.of(parent.getComponents())
            .filter(Container.class::isInstance)
            .map(Container.class::cast)
            .flatMap(c -> Stream.concat(Stream.of(c), descendants(c)));
      }
    }