Reputation: 15
I'm working with a Java Swing application and facing a challenge with customizing the JFileChooser component. Specifically, I need to change the background color of the JTextField used for editing file or folder names within the JFileChooser.
The file and folder list in JFileChooser is represented by a JList, which, as far as I know, does not provide a direct method to access or modify the cell editor.
I attempted to override the getListCellRendererComponent() method of DefaultListCellRenderer to achieve this, but this approach does not grant me access to the JTextField component.
Is there a way to customize the JTextField within JFileChooser for editing file or folder names, specifically to change its background color?
Upvotes: 0
Views: 93
Reputation: 15
Also I find out alternative solution.
public static void main(String[] args) {
JFileChooser chooser = new JFileChooser();
UIManager.put("TextField.selectionBackground", Color.YELLOW);
UIManager.put("TextField.background", Color.GRAY);
UIManager.put("TextField.foreground", Color.BLACK);
chooser.showOpenDialog(null);
}
Upvotes: 0
Reputation: 324078
You can add a ContainerListener
to the JList
of the JFileChooser
to be notified when the text field is added to the JList to edit the file name:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class FileChooserEditField
{
private static void createAndShowUI()
{
JFileChooser fileChooser = new JFileChooser(".");
// Access the JList and add a ContainerListener to the list
JList list = SwingUtils.getDescendantsOfType(JList.class, fileChooser).get(0);
list.addContainerListener( new ContainerAdapter()
{
@Override
public void componentAdded(ContainerEvent e)
{
Component c = e.getChild();
c.setBackground( Color.YELLOW );
}
});
fileChooser.showOpenDialog(null);
}
public static void main(String[] args)
{
EventQueue.invokeLater(() -> createAndShowUI());
}
}
This solution uses the Swing Utils class to search the file chooser for the JList component.
Upvotes: 1
Reputation: 711
The JTextField in question is editCell
. You could obtain it via reflection, however I don't think this is a good idea.
Here's a rough prototype (currently only the second selection sets the background correctly):
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileSystemView;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Field;
public class Demo {
private Demo() {
JFrame jframe = new JFrame("Test");
JButton button = new JButton("Click me");
final JFileChooser fc = new JFileChooser();
fc.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
Object filepane = fc.getComponent(2);
try {
Field field = filepane.getClass().getDeclaredField("editCell");
field.setAccessible(true);
JTextField textfield = (JTextField) field.get(filepane);
if (textfield != null) {
textfield.setBackground(Color.yellow);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
});
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int returnVal = fc.showOpenDialog((Component) e.getSource());
}
});
jframe.add(button, BorderLayout.CENTER);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.pack();
jframe.setSize(400, 300);
jframe.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Demo();
}
});
}
}
If you are using an SDK greater than Java 9, you also need to make packages from sun.swing.* available in your run configuration:
--add-opens=java.desktop/sun.swing=ALL-UNNAMED
Upvotes: 0