2

I need to insert a JFileChooser dialog in my Swing application, and I would like to customize its look so that it matches that of the other windows. Specifically, I am having troubles:

  1. changing the background color of the JFileChooser
  2. changing the shape of the JTextField showing the folder path

I am including three classes below which exemplify the problem I am facing.

This is the custom JDialog class (the idea to embed the JFileChooser in a JDialog came from here Possible to remove Title bar from JFileChooser?)

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FileChooserDialog extends JDialog {

    private ModifiedFileChooser modifiedFileChooser;

    public FileChooserDialog(ModifiedFileChooser modifiedFileChooser) {
        super();
        this.modifiedFileChooser = modifiedFileChooser;
        setUndecorated(true);
        setLayout(new BorderLayout());
        add(modifiedFileChooser, BorderLayout.CENTER);
        setBackground(new Color(180, 14, 14));

        pack();
        setVisible(true);
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        JButton openB = new JButton("Open");
        openB.setPreferredSize(new Dimension(50,20));
        frame.setLayout(new BorderLayout());
        frame.add(openB, BorderLayout.CENTER);

        openB.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new FileChooserDialog(new ModifiedFileChooser());
            }
        });

        frame.setPreferredSize(new Dimension(300, 200));
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);

    }
}

This is the custom JFileChooser class (I referred to this post on how to customize a JFileChooser Creating custom JFileChooser)

import javax.swing.*;
import java.awt.*;

public class ModifiedFileChooser extends JFileChooser {

    public ModifiedFileChooser() {
        super();

        customizeFileChooser(this.getComponents());
        setBackground(new Color(180, 14, 14));
        repaint();
    }

    private void customizeFileChooser(Component[] comp) {

        for (int x = 0; x < comp.length; x++) {

            if (comp[x] instanceof JScrollPane) {
                ((JScrollPane) comp[x]).setBackground(new Color(180, 14, 14));
            }
            
            if (comp[x] instanceof JPanel) {

                ((JPanel) comp[x]).setBackground(new Color(180, 14, 14));

                customizeFileChooser(((JPanel) comp[x]).getComponents());

                Component[] c = ((JPanel) comp[x]).getComponents();

                for (int i = 0; i < c.length; i++) {

                    if (c[i] instanceof JTextField) {
                        int previousSize = ((JTextField) c[i]).getColumns();
                        c[i] = new RoundedTextField(previousSize);

                    }

                    if (c[i] instanceof JPanel) {
                        ((JPanel) c[i]).setBackground(new Color(180, 14, 14));
                    }

                    if (c[i] instanceof JScrollPane) {
                        ((JScrollPane) c[i]).setBackground(new Color(180, 14, 14));
                    }

                }
            }
        }
    }
}

This is the custom JTextField class (the code is taken from this post: Java Swing rounded border for Jtextfield)

import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;

public class RoundedTextField extends JTextField {

    private Shape shape;
    public RoundedTextField(int size) {
        super(size);
        setOpaque(false);
    }
    protected void paintComponent(Graphics g) {
        g.setColor(getBackground());
        g.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, 15, 15);
        super.paintComponent(g);
    }
    protected void paintBorder(Graphics g) {
        g.setColor(getForeground());
        g.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 15, 15);
    }
    public boolean contains(int x, int y) {
        if (shape == null || !shape.getBounds().equals(getBounds())) {
            shape = new RoundRectangle2D.Float(0, 0, getWidth()-1, getHeight()-1, 15, 15);
        }
        return shape.contains(x, y);
    }
}

The dialog that is diaplyed after pressing the button in the frame looks like this:

Dialog with explanation of current issues

Ideally, I would want the textfield close to the "File Name:" label to have rounded corners, and the background of the JFileChooser to be red instead of grey.

Many thanks in advance for any help on this!

andy_07
  • 21
  • 5
  • The code doesn't seem to match the result picture – XtremeBaumer Sep 27 '22 at 11:09
  • Also would help if you could draft a picture with which components should have which color – XtremeBaumer Sep 27 '22 at 11:19
  • You are hopefully aware that the first step would be to pick a nice look-and-feel, like Nimbus. – Joop Eggen Sep 27 '22 at 12:49
  • @XtremeBaumer Thanks for flagging that: I edited the initial code in the question and added to the previous picture an explanation of what I am expecting to get. – andy_07 Sep 27 '22 at 12:59
  • @JoopEggen I am, but actually so far Metal has served me well enough, since I always managed to change how some elements looked when needed. – andy_07 Sep 27 '22 at 13:03
  • Aha, I stumbled over that Metal theme, as it is not my favorite. So it is intentional. One can also globally customize JTextField and others with the UI* classes. You can walk child components, and the scroll view to reach the entire background component. The JTextField with rounded borders I would maybe develop separately. – Joop Eggen Sep 27 '22 at 13:26
  • @JoopEggen Thank you for the suggestions! Could you please provide an example of how I can use the UI* classes in this context (I have never used them except for UIManager for setting the general look and feel)? Indeed I have already accessed some of the child components (panels) in the code above, and managed to change some backgrounds to red. I will try to see what happens when I modify the background of other components. – andy_07 Sep 27 '22 at 14:01
  • Looking at your picture, I'd just forget the Swing JFileChooser and create my own custom file chooser using a JDialog from other Swing components. – Gilbert Le Blanc Sep 27 '22 at 14:12
  • I moved on to JavaFX, Install the sources, src.zip, and look at the children of [`ComponentUI`](https://docs.oracle.com/javase/8/docs/api/javax/swing/plaf/ComponentUI.html). UIManager also holds things. Maybe you can install your own [`FileChooserUI`](https://docs.oracle.com/javase/8/docs/api/javax/swing/plaf/FileChooserUI.html) – Joop Eggen Sep 27 '22 at 14:57
  • Have you tried to use `java.awt.FileDialog` if you want it to look like the native OS? – Anthony Oct 06 '22 at 16:19

0 Answers0