4

Normally when you use setEditable(false) or setEnabled(false), the background/foreground color of the JTextField becomes 'grayed out'. However, if a background color had previously been set using setBackground(color) (for example to white), then the call to setEnabled or setEditable will not affect the background color anymore. Instead, it is overridden by the previously set color.

In WinForms (.NET) this is solved by "resetting" the background color to a non-overriding default value, namely Color.Empty. That would cause a text box to regain the standard behavior. However, I haven't found a similar "default value" for JTextField. How do I revert the JTextField to use the default colors and automatically switch the color when it is being disabled or set to read only? The foreground color has a similar issue.

dialer
  • 4,348
  • 6
  • 33
  • 56

2 Answers2

8

You need to reset the background color of the field to its default value.

The default UI delegate is looking for a UIResource in order to determine the correct shadings to use for the given field (based on the installed look and feel).

You can reset the background color using:

JTextField#setBackground(UIManager.getColor("TextField.background"))

Alternatively, you could construct a custom UIResource for your custom background.

Take a look at ColorUIResource for more details.

Mike D
  • 4,938
  • 6
  • 43
  • 99
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • or use JTextField.setDisabled.... (JSpinner, JFormattedTextField, editable JComboBox) instead of any woodoo – mKorbel Mar 29 '13 at 06:07
  • @mKorbel I've only looked a JTextComponent, but as far as I can see, it only allows you to set the disabled text color, besides, why make things easy ;) – MadProgrammer Mar 29 '13 at 06:44
  • This works, when you call it in this order: `textField.setBackground(UIManager.getColor(...)); textField.setEditable(false);`, but for some reason the background is still white when you call `setEditable(false)` first. Whetever, works anyway. – dialer Mar 29 '13 at 10:02
  • When you call setEditable, the UI delegate checks the background color and makes a decision based on what type of object the result is. But when set the background color, it just reprints the component, hecne the reason you need to set the background color first – MadProgrammer Mar 29 '13 at 20:05
  • When you `textField.setEnabled(false)` this grays the field nicely (foreground color), but has a side effect that was unacceptable for my case: It makes the entry unfocusable. This means you can't select and copy the value, for instance. – Joshua Goldberg Jan 19 '15 at 03:55
  • @JoshuaGoldberg But what did you think `setEnabled` would do? Have you considered using `setEditable` instead? – MadProgrammer Jan 19 '15 at 04:03
  • As an update and side note, JTextArea (note, not JTextField) is specifically prohibited from doing this. `JTextComponent#setEditable(b)` changes the `editable` bound property; the `BasicTextUI` notices that and calls its `updateBackground` subroutine. That method checks for `JTextArea` and bails out for reasons described in a comment there. (It's the rest of that function which does the UIResource check described above.) So if you came to this page looking for JTextArea help, that's why. A possible... – Ti Strga Mar 05 '21 at 17:48
  • ...workaround would be to anonymously subclass a JTextArea instance and override `setEditable` to additionally swap background colors, but of course that's not always advisable in every situation. – Ti Strga Mar 05 '21 at 17:49
  • @TiStrga Or create a custom UI delegate – MadProgrammer Mar 06 '21 at 00:00
5

How do I revert the JTextField to use the default colors

textField.setBackground( null );

automatically switch the color when it is being disabled or set to read only?

Use a PropertyChangeListener:

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.*;

public class SSCCE extends JPanel implements PropertyChangeListener
{
    public SSCCE()
    {
        JTextField textField = new JTextField("Some Text");
        // Uncomment and run again to see the difference
        //textField.addPropertyChangeListener( this );
        textField.setBackground(Color.RED);
        textField.setEditable(false);
        add(textField);
    }

    public void propertyChange(PropertyChangeEvent e)
    {
        System.out.println(e.getPropertyName());
        JTextField textField = (JTextField)e.getSource();

        if ("editable".equals(e.getPropertyName()))
            textField.setBackground( null );
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new SSCCE() );
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288